summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorsimonmar <unknown>2001-06-28 14:15:04 +0000
committersimonmar <unknown>2001-06-28 14:15:04 +0000
commit4fb94ae5e5d632748fa2e6c35e259eccc5a1a3f4 (patch)
treedd5bc589e37efe68e84099180c16359a3acdb06b /libraries
downloadhaskell-4fb94ae5e5d632748fa2e6c35e259eccc5a1a3f4.tar.gz
[project @ 2001-06-28 14:15:04 by simonmar]
First cut of the Haskell Core Libraries ======================================= NOTE: it's not meant to be a working snapshot. The code is just here to look at and so the NHC/Hugs guys can start playing around with it. There is no build system. For GHC, the libraries tree is intended to be grafted onto an existing fptools/ tree, and the Makefile in libraries/core is a quick hack for that setup. This won't work at the moment without the other changes needed in fptools/ghc, which I haven't committed because they'll cause breakage. However, with the changes required these sources build a working Prelude and libraries. The layout mostly follows the one we agreed on, with one or two minor changes; in particular the Data/Array layout probably isn't final (there are several choices here). The document is in libraries/core/doc as promised. The cbits stuff is just a copy of ghc/lib/std/cbits and has GHC-specific stuff in it. We should really separate the compiler-specific C support from any compiler-independent C support there might be. Don't pay too much attention to the portability or stability status indicated in the header of each source file at the moment - I haven't gone through to make sure they're all consistent and make sense. I'm using non-literate source outside of GHC/. Hope that's ok with everyone. We need to discuss how the build system is going to work...
Diffstat (limited to 'libraries')
-rw-r--r--libraries/base/Control/Concurrent.hs199
-rw-r--r--libraries/base/Control/Concurrent/CVar.hs57
-rw-r--r--libraries/base/Control/Concurrent/Chan.hs119
-rw-r--r--libraries/base/Control/Concurrent/MVar.hs95
-rw-r--r--libraries/base/Control/Concurrent/QSem.hs67
-rw-r--r--libraries/base/Control/Concurrent/QSemN.hs60
-rw-r--r--libraries/base/Control/Concurrent/SampleVar.hs98
-rw-r--r--libraries/base/Control/Exception.hs226
-rw-r--r--libraries/base/Control/Monad.hs160
-rw-r--r--libraries/base/Control/Monad/Cont.hs122
-rw-r--r--libraries/base/Control/Monad/Error.hs224
-rw-r--r--libraries/base/Control/Monad/Fix.hs55
-rw-r--r--libraries/base/Control/Monad/Identity.hs63
-rw-r--r--libraries/base/Control/Monad/List.hs87
-rw-r--r--libraries/base/Control/Monad/Monoid.hs58
-rw-r--r--libraries/base/Control/Monad/RWS.hs170
-rw-r--r--libraries/base/Control/Monad/Reader.hs143
-rw-r--r--libraries/base/Control/Monad/ST.hs53
-rw-r--r--libraries/base/Control/Monad/ST/Lazy.hs247
-rw-r--r--libraries/base/Control/Monad/ST/Strict.hs22
-rw-r--r--libraries/base/Control/Monad/State.hs227
-rw-r--r--libraries/base/Control/Monad/Trans.hs46
-rw-r--r--libraries/base/Control/Monad/Writer.hs170
-rw-r--r--libraries/base/Control/Parallel.hs62
-rw-r--r--libraries/base/Control/Parallel/Strategies.hs964
-rw-r--r--libraries/base/Data/Array.hs145
-rw-r--r--libraries/base/Data/Array/Base.hs1163
-rw-r--r--libraries/base/Data/Array/IArray.hs42
-rw-r--r--libraries/base/Data/Array/IO.hs365
-rw-r--r--libraries/base/Data/Array/MArray.hs47
-rw-r--r--libraries/base/Data/Array/ST.hs35
-rw-r--r--libraries/base/Data/Array/Unboxed.hs25
-rw-r--r--libraries/base/Data/Bits.hs143
-rw-r--r--libraries/base/Data/Bool.hs28
-rw-r--r--libraries/base/Data/Char.hs51
-rw-r--r--libraries/base/Data/Complex.hs153
-rw-r--r--libraries/base/Data/Dynamic.hs288
-rw-r--r--libraries/base/Data/Either.hs25
-rw-r--r--libraries/base/Data/IORef.hs57
-rw-r--r--libraries/base/Data/Int.hs37
-rw-r--r--libraries/base/Data/Ix.hs43
-rw-r--r--libraries/base/Data/List.hs537
-rw-r--r--libraries/base/Data/Maybe.hs75
-rw-r--r--libraries/base/Data/PackedString.hs914
-rw-r--r--libraries/base/Data/Ratio.hs81
-rw-r--r--libraries/base/Data/STRef.hs33
-rw-r--r--libraries/base/Data/Word.hs38
-rw-r--r--libraries/base/Debug/Trace.hs41
-rw-r--r--libraries/base/Foreign.hs44
-rw-r--r--libraries/base/Foreign/C.hs28
-rw-r--r--libraries/base/Foreign/C/Error.hs514
-rw-r--r--libraries/base/Foreign/C/String.hs179
-rw-r--r--libraries/base/Foreign/C/Types.hs114
-rw-r--r--libraries/base/Foreign/C/TypesISO.hs84
-rw-r--r--libraries/base/Foreign/ForeignPtr.hs88
-rw-r--r--libraries/base/Foreign/Marshal/Alloc.hs115
-rw-r--r--libraries/base/Foreign/Marshal/Array.hs268
-rw-r--r--libraries/base/Foreign/Marshal/Error.hs81
-rw-r--r--libraries/base/Foreign/Marshal/Utils.hs168
-rw-r--r--libraries/base/Foreign/Ptr.hs55
-rw-r--r--libraries/base/Foreign/StablePtr.hs35
-rw-r--r--libraries/base/Foreign/Storable.hs33
-rw-r--r--libraries/base/GHC/Arr.lhs574
-rw-r--r--libraries/base/GHC/Base.lhs761
-rw-r--r--libraries/base/GHC/ByteArr.lhs184
-rw-r--r--libraries/base/GHC/Conc.lhs202
-rw-r--r--libraries/base/GHC/Dynamic.lhs35
-rw-r--r--libraries/base/GHC/Enum.lhs414
-rw-r--r--libraries/base/GHC/Err.hi-boot12
-rw-r--r--libraries/base/GHC/Err.lhs129
-rw-r--r--libraries/base/GHC/Exception.lhs123
-rw-r--r--libraries/base/GHC/Float.lhs892
-rw-r--r--libraries/base/GHC/Handle.hsc1191
-rw-r--r--libraries/base/GHC/IO.hsc787
-rw-r--r--libraries/base/GHC/IOBase.lhs605
-rw-r--r--libraries/base/GHC/Int.lhs599
-rw-r--r--libraries/base/GHC/List.lhs610
-rw-r--r--libraries/base/GHC/Main.lhs24
-rw-r--r--libraries/base/GHC/Maybe.lhs64
-rw-r--r--libraries/base/GHC/Num.hi-boot14
-rw-r--r--libraries/base/GHC/Num.lhs447
-rw-r--r--libraries/base/GHC/Pack.lhs231
-rw-r--r--libraries/base/GHC/Posix.hsc295
-rw-r--r--libraries/base/GHC/Prim.hi-boot441
-rw-r--r--libraries/base/GHC/Ptr.lhs61
-rw-r--r--libraries/base/GHC/Read.lhs608
-rw-r--r--libraries/base/GHC/Real.lhs369
-rw-r--r--libraries/base/GHC/ST.lhs127
-rw-r--r--libraries/base/GHC/STRef.lhs30
-rw-r--r--libraries/base/GHC/Show.lhs378
-rw-r--r--libraries/base/GHC/Stable.lhs54
-rw-r--r--libraries/base/GHC/Storable.lhs289
-rw-r--r--libraries/base/GHC/TopHandler.lhs85
-rw-r--r--libraries/base/GHC/Tup.lhs238
-rw-r--r--libraries/base/GHC/Weak.lhs65
-rw-r--r--libraries/base/GHC/Word.lhs737
-rw-r--r--libraries/base/Main.hi-boot13
-rw-r--r--libraries/base/Makefile74
-rw-r--r--libraries/base/Prelude.hs126
-rw-r--r--libraries/base/System/CPUTime.hsc126
-rw-r--r--libraries/base/System/Cmd.hsc55
-rw-r--r--libraries/base/System/Environment.hs83
-rw-r--r--libraries/base/System/Exit.hs44
-rw-r--r--libraries/base/System/IO.hs192
-rw-r--r--libraries/base/System/IO/Directory.hsc555
-rw-r--r--libraries/base/System/IO/Unsafe.hs26
-rw-r--r--libraries/base/System/Info.hs32
-rw-r--r--libraries/base/System/Locale.hs76
-rw-r--r--libraries/base/System/Mem/StableName.hs67
-rw-r--r--libraries/base/System/Mem/Weak.hs56
-rw-r--r--libraries/base/System/Random.hs279
-rw-r--r--libraries/base/System/Time.hsc619
-rw-r--r--libraries/base/Text/Read.hs32
-rw-r--r--libraries/base/Text/Show.hs34
-rw-r--r--libraries/base/Text/Show/Functions.hs22
-rw-r--r--libraries/base/cbits/Makefile20
-rw-r--r--libraries/base/cbits/errno.c15
-rw-r--r--libraries/base/cbits/inputReady.c53
-rw-r--r--libraries/base/cbits/lockFile.c128
-rw-r--r--libraries/base/cbits/system.c87
-rw-r--r--libraries/base/cbits/writeError.c51
-rw-r--r--libraries/base/doc/libraries.sgml1156
-rw-r--r--libraries/base/include/CTypes.h335
-rw-r--r--libraries/base/include/Dynamic.h27
-rw-r--r--libraries/base/include/HsCore.h94
-rw-r--r--libraries/base/include/PackedString.h14
-rw-r--r--libraries/base/include/ghc_errno.h15
-rw-r--r--libraries/base/include/lockFile.h10
128 files changed, 26157 insertions, 0 deletions
diff --git a/libraries/base/Control/Concurrent.hs b/libraries/base/Control/Concurrent.hs
new file mode 100644
index 0000000000..033f2cc91c
--- /dev/null
+++ b/libraries/base/Control/Concurrent.hs
@@ -0,0 +1,199 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Concurrent
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Concurrent.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-- A common interface to a collection of useful concurrency
+-- abstractions.
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent
+ ( module Control.Concurrent.Chan
+ , module Control.Concurrent.CVar
+ , module Control.Concurrent.MVar
+ , module Control.Concurrent.QSem
+ , module Control.Concurrent.QSemN
+ , module Control.Concurrent.SampleVar
+
+#ifdef __HUGS__
+ , forkIO -- :: IO () -> IO ()
+#elif defined(__GLASGOW_HASKELL__)
+ , ThreadId
+
+ -- Forking and suchlike
+ , myThreadId -- :: IO ThreadId
+ , killThread -- :: ThreadId -> IO ()
+ , throwTo -- :: ThreadId -> Exception -> IO ()
+#endif
+ , par -- :: a -> b -> b
+ , seq -- :: a -> b -> b
+#ifdef __GLASGOW_HASKELL__
+ , fork -- :: a -> b -> b
+#endif
+ , yield -- :: IO ()
+
+#ifdef __GLASGOW_HASKELL__
+ , threadDelay -- :: Int -> IO ()
+ , threadWaitRead -- :: Int -> IO ()
+ , threadWaitWrite -- :: Int -> IO ()
+#endif
+
+ -- merging of streams
+ , mergeIO -- :: [a] -> [a] -> IO [a]
+ , nmergeIO -- :: [[a]] -> IO [a]
+ ) where
+
+import Prelude
+
+import Control.Exception as Exception
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Conc
+import GHC.TopHandler ( reportStackOverflow, reportError )
+import GHC.IOBase ( IO(..) )
+import GHC.IOBase ( unsafePerformIO , unsafeInterleaveIO )
+import GHC.Base ( fork# )
+import GHC.Prim ( Addr#, unsafeCoerce# )
+#endif
+
+#ifdef __HUGS__
+import IOExts ( unsafeInterleaveIO, unsafePerformIO )
+import ConcBase
+#endif
+
+import Control.Concurrent.MVar
+import Control.Concurrent.CVar
+import Control.Concurrent.Chan
+import Control.Concurrent.QSem
+import Control.Concurrent.QSemN
+import Control.Concurrent.SampleVar
+
+#ifdef __GLASGOW_HASKELL__
+infixr 0 `fork`
+#endif
+
+-- Thread Ids, specifically the instances of Eq and Ord for these things.
+-- The ThreadId type itself is defined in std/PrelConc.lhs.
+
+-- Rather than define a new primitve, we use a little helper function
+-- cmp_thread in the RTS.
+
+#ifdef __GLASGOW_HASKELL__
+foreign import ccall "cmp_thread" unsafe cmp_thread :: Addr# -> Addr# -> Int
+-- Returns -1, 0, 1
+
+cmpThread :: ThreadId -> ThreadId -> Ordering
+cmpThread (ThreadId t1) (ThreadId t2) =
+ case cmp_thread (unsafeCoerce# t1) (unsafeCoerce# t2) of
+ -1 -> LT
+ 0 -> EQ
+ _ -> GT -- must be 1
+
+instance Eq ThreadId where
+ t1 == t2 =
+ case t1 `cmpThread` t2 of
+ EQ -> True
+ _ -> False
+
+instance Ord ThreadId where
+ compare = cmpThread
+
+forkIO :: IO () -> IO ThreadId
+forkIO action = IO $ \ s ->
+ case (fork# action_plus s) of (# s1, id #) -> (# s1, ThreadId id #)
+ where
+ action_plus = Exception.catch action childHandler
+
+childHandler :: Exception -> IO ()
+childHandler err = Exception.catch (real_handler err) childHandler
+
+real_handler :: Exception -> IO ()
+real_handler ex =
+ case ex of
+ -- ignore thread GC and killThread exceptions:
+ BlockedOnDeadMVar -> return ()
+ AsyncException ThreadKilled -> return ()
+
+ -- report all others:
+ AsyncException StackOverflow -> reportStackOverflow False
+ ErrorCall s -> reportError False s
+ other -> reportError False (showsPrec 0 other "\n")
+
+{-# INLINE fork #-}
+fork :: a -> b -> b
+fork x y = unsafePerformIO (forkIO (x `seq` return ())) `seq` y
+
+#endif /* __GLASGOW_HASKELL__ */
+
+
+max_buff_size :: Int
+max_buff_size = 1
+
+mergeIO :: [a] -> [a] -> IO [a]
+nmergeIO :: [[a]] -> IO [a]
+
+mergeIO ls rs
+ = newEmptyMVar >>= \ tail_node ->
+ newMVar tail_node >>= \ tail_list ->
+ newQSem max_buff_size >>= \ e ->
+ newMVar 2 >>= \ branches_running ->
+ let
+ buff = (tail_list,e)
+ in
+ forkIO (suckIO branches_running buff ls) >>
+ forkIO (suckIO branches_running buff rs) >>
+ takeMVar tail_node >>= \ val ->
+ signalQSem e >>
+ return val
+
+type Buffer a
+ = (MVar (MVar [a]), QSem)
+
+suckIO :: MVar Int -> Buffer a -> [a] -> IO ()
+
+suckIO branches_running buff@(tail_list,e) vs
+ = case vs of
+ [] -> takeMVar branches_running >>= \ val ->
+ if val == 1 then
+ takeMVar tail_list >>= \ node ->
+ putMVar node [] >>
+ putMVar tail_list node
+ else
+ putMVar branches_running (val-1)
+ (x:xs) ->
+ waitQSem e >>
+ takeMVar tail_list >>= \ node ->
+ newEmptyMVar >>= \ next_node ->
+ unsafeInterleaveIO (
+ takeMVar next_node >>= \ y ->
+ signalQSem e >>
+ return y) >>= \ next_node_val ->
+ putMVar node (x:next_node_val) >>
+ putMVar tail_list next_node >>
+ suckIO branches_running buff xs
+
+nmergeIO lss
+ = let
+ len = length lss
+ in
+ newEmptyMVar >>= \ tail_node ->
+ newMVar tail_node >>= \ tail_list ->
+ newQSem max_buff_size >>= \ e ->
+ newMVar len >>= \ branches_running ->
+ let
+ buff = (tail_list,e)
+ in
+ mapIO (\ x -> forkIO (suckIO branches_running buff x)) lss >>
+ takeMVar tail_node >>= \ val ->
+ signalQSem e >>
+ return val
+ where
+ mapIO f xs = sequence (map f xs)
diff --git a/libraries/base/Control/Concurrent/CVar.hs b/libraries/base/Control/Concurrent/CVar.hs
new file mode 100644
index 0000000000..8e16596088
--- /dev/null
+++ b/libraries/base/Control/Concurrent/CVar.hs
@@ -0,0 +1,57 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Concurrent.CVar
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: CVar.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-- Channel variables are one-element channels.
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent.CVar
+ ( -- abstract
+ CVar
+ , newCVar -- :: IO (CVar a)
+ , writeCVar -- :: CVar a -> a -> IO ()
+ , readCVar -- :: CVar a -> IO a
+ ) where
+
+import Prelude
+
+import Control.Concurrent.MVar
+
+-- @MVars@ provide the basic mechanisms for synchronising access to a
+-- shared resource. @CVars@, or channel variables, provide an abstraction
+-- that guarantee that the producer is not allowed to run riot, but
+-- enforces the interleaved access to the channel variable,i.e., a
+-- producer is forced to wait up for a consumer to remove the previous
+-- value before it can deposit a new one in the @CVar@.
+
+data CVar a
+ = CVar (MVar a) -- prod -> cons
+ (MVar ()) -- cons -> prod
+
+newCVar :: IO (CVar a)
+newCVar
+ = newEmptyMVar >>= \ datum ->
+ newMVar () >>= \ ack ->
+ return (CVar datum ack)
+
+writeCVar :: CVar a -> a -> IO ()
+
+writeCVar (CVar datum ack) val
+ = takeMVar ack >>
+ putMVar datum val >>
+ return ()
+
+readCVar :: CVar a -> IO a
+readCVar (CVar datum ack)
+ = takeMVar datum >>= \ val ->
+ putMVar ack () >>
+ return val
diff --git a/libraries/base/Control/Concurrent/Chan.hs b/libraries/base/Control/Concurrent/Chan.hs
new file mode 100644
index 0000000000..29423e1d84
--- /dev/null
+++ b/libraries/base/Control/Concurrent/Chan.hs
@@ -0,0 +1,119 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Concurrent.Chan
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Chan.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Standard, unbounded channel abstraction.
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent.Chan
+ ( Chan -- abstract
+
+ -- creator
+ , newChan -- :: IO (Chan a)
+
+ -- operators
+ , writeChan -- :: Chan a -> a -> IO ()
+ , readChan -- :: Chan a -> IO a
+ , dupChan -- :: Chan a -> IO (Chan a)
+ , unGetChan -- :: Chan a -> a -> IO ()
+
+ , isEmptyChan -- :: Chan a -> IO Bool
+
+ -- stream interface
+ , getChanContents -- :: Chan a -> IO [a]
+ , writeList2Chan -- :: Chan a -> [a] -> IO ()
+
+ ) where
+
+import Prelude
+
+import System.IO.Unsafe ( unsafeInterleaveIO )
+import Control.Concurrent.MVar
+
+-- A channel is represented by two @MVar@s keeping track of the two ends
+-- of the channel contents,i.e., the read- and write ends. Empty @MVar@s
+-- are used to handle consumers trying to read from an empty channel.
+
+data Chan a
+ = Chan (MVar (Stream a))
+ (MVar (Stream a))
+
+type Stream a = MVar (ChItem a)
+
+data ChItem a = ChItem a (Stream a)
+
+-- See the Concurrent Haskell paper for a diagram explaining the
+-- how the different channel operations proceed.
+
+-- @newChan@ sets up the read and write end of a channel by initialising
+-- these two @MVar@s with an empty @MVar@.
+
+newChan :: IO (Chan a)
+newChan = do
+ hole <- newEmptyMVar
+ read <- newMVar hole
+ write <- newMVar hole
+ return (Chan read write)
+
+-- To put an element on a channel, a new hole at the write end is created.
+-- What was previously the empty @MVar@ at the back of the channel is then
+-- filled in with a new stream element holding the entered value and the
+-- new hole.
+
+writeChan :: Chan a -> a -> IO ()
+writeChan (Chan _read write) val = do
+ new_hole <- newEmptyMVar
+ modifyMVar_ write $ \old_hole -> do
+ putMVar old_hole (ChItem val new_hole)
+ return new_hole
+
+readChan :: Chan a -> IO a
+readChan (Chan read _write) = do
+ modifyMVar read $ \read_end -> do
+ (ChItem val new_read_end) <- readMVar read_end
+ -- Use readMVar here, not takeMVar,
+ -- else dupChan doesn't work
+ return (new_read_end, val)
+
+dupChan :: Chan a -> IO (Chan a)
+dupChan (Chan _read write) = do
+ hole <- readMVar write
+ new_read <- newMVar hole
+ return (Chan new_read write)
+
+unGetChan :: Chan a -> a -> IO ()
+unGetChan (Chan read _write) val = do
+ new_read_end <- newEmptyMVar
+ modifyMVar_ read $ \read_end -> do
+ putMVar new_read_end (ChItem val read_end)
+ return new_read_end
+
+isEmptyChan :: Chan a -> IO Bool
+isEmptyChan (Chan read write) = do
+ withMVar read $ \r -> do
+ w <- readMVar write
+ let eq = r == w
+ eq `seq` return eq
+
+-- Operators for interfacing with functional streams.
+
+getChanContents :: Chan a -> IO [a]
+getChanContents ch
+ = unsafeInterleaveIO (do
+ x <- readChan ch
+ xs <- getChanContents ch
+ return (x:xs)
+ )
+
+-------------
+writeList2Chan :: Chan a -> [a] -> IO ()
+writeList2Chan ch ls = sequence_ (map (writeChan ch) ls)
diff --git a/libraries/base/Control/Concurrent/MVar.hs b/libraries/base/Control/Concurrent/MVar.hs
new file mode 100644
index 0000000000..7832c2eca3
--- /dev/null
+++ b/libraries/base/Control/Concurrent/MVar.hs
@@ -0,0 +1,95 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Concurrent.MVar
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: MVar.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- MVars: Synchronising variables
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent.MVar
+ ( MVar -- abstract
+ , newEmptyMVar -- :: IO (MVar a)
+ , newMVar -- :: a -> IO (MVar a)
+ , takeMVar -- :: MVar a -> IO a
+ , putMVar -- :: MVar a -> a -> IO ()
+ , readMVar -- :: MVar a -> IO a
+ , swapMVar -- :: MVar a -> a -> IO a
+ , tryTakeMVar -- :: MVar a -> IO (Maybe a)
+ , tryPutMVar -- :: MVar a -> a -> IO Bool
+ , isEmptyMVar -- :: MVar a -> IO Bool
+ , withMVar -- :: MVar a -> (a -> IO b) -> IO b
+ , modifyMVar_ -- :: MVar a -> (a -> IO a) -> IO ()
+ , modifyMVar -- :: MVar a -> (a -> IO (a,b)) -> IO b
+ , addMVarFinalizer -- :: MVar a -> IO () -> IO ()
+ ) where
+
+#ifdef __HUGS__
+import ConcBase ( MVar, newEmptyMVar, newMVar, takeMVar, putMVar,
+ tryTakeMVar, tryPutMVar, isEmptyMVar,
+ readMVar, swapMVar,
+ )
+import Prelude hiding( catch )
+#endif
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Conc ( MVar, newEmptyMVar, newMVar, takeMVar, putMVar,
+ tryTakeMVar, tryPutMVar, isEmptyMVar, addMVarFinalizer
+ )
+#endif
+
+import Control.Exception as Exception
+
+#ifdef __HUGS__
+-- This is as close as Hugs gets to providing throw
+throw :: Exception -> IO a
+throw = throwIO
+#endif
+
+#ifdef __GLASGOW_HASKELL__
+readMVar :: MVar a -> IO a
+readMVar m =
+ block $ do
+ a <- takeMVar m
+ putMVar m a
+ return a
+
+swapMVar :: MVar a -> a -> IO a
+swapMVar mvar new = modifyMVar mvar (\old -> return (new,old))
+#endif
+
+-- put back the same value, return something
+withMVar :: MVar a -> (a -> IO b) -> IO b
+withMVar m io =
+ block $ do
+ a <- takeMVar m
+ b <- Exception.catch (unblock (io a))
+ (\e -> do putMVar m a; throw e)
+ putMVar m a
+ return b
+
+-- put back a new value, return ()
+modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()
+modifyMVar_ m io =
+ block $ do
+ a <- takeMVar m
+ a' <- Exception.catch (unblock (io a))
+ (\e -> do putMVar m a; throw e)
+ putMVar m a'
+
+-- put back a new value, return something
+modifyMVar :: MVar a -> (a -> IO (a,b)) -> IO b
+modifyMVar m io =
+ block $ do
+ a <- takeMVar m
+ (a',b) <- Exception.catch (unblock (io a))
+ (\e -> do putMVar m a; throw e)
+ putMVar m a'
+ return b
diff --git a/libraries/base/Control/Concurrent/QSem.hs b/libraries/base/Control/Concurrent/QSem.hs
new file mode 100644
index 0000000000..6ffba7d5a3
--- /dev/null
+++ b/libraries/base/Control/Concurrent/QSem.hs
@@ -0,0 +1,67 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Concurrent.QSem
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: QSem.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- General semaphores
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent.QSem
+ ( QSem, -- abstract
+ newQSem, -- :: Int -> IO QSem
+ waitQSem, -- :: QSem -> IO ()
+ signalQSem -- :: QSem -> IO ()
+ ) where
+
+import Control.Concurrent.MVar
+
+-- General semaphores are also implemented readily in terms of shared
+-- @MVar@s, only have to catch the case when the semaphore is tried
+-- waited on when it is empty (==0). Implement this in the same way as
+-- shared variables are implemented - maintaining a list of @MVar@s
+-- representing threads currently waiting. The counter is a shared
+-- variable, ensuring the mutual exclusion on its access.
+
+newtype QSem = QSem (MVar (Int, [MVar ()]))
+
+newQSem :: Int -> IO QSem
+newQSem init = do
+ sem <- newMVar (init,[])
+ return (QSem sem)
+
+waitQSem :: QSem -> IO ()
+waitQSem (QSem sem) = do
+ (avail,blocked) <- takeMVar sem -- gain ex. access
+ if avail > 0 then
+ putMVar sem (avail-1,[])
+ else do
+ block <- newEmptyMVar
+ {-
+ Stuff the reader at the back of the queue,
+ so as to preserve waiting order. A signalling
+ process then only have to pick the MVar at the
+ front of the blocked list.
+
+ The version of waitQSem given in the paper could
+ lead to starvation.
+ -}
+ putMVar sem (0, blocked++[block])
+ takeMVar block
+
+signalQSem :: QSem -> IO ()
+signalQSem (QSem sem) = do
+ (avail,blocked) <- takeMVar sem
+ case blocked of
+ [] -> putMVar sem (avail+1,[])
+
+ (block:blocked') -> do
+ putMVar sem (0,blocked')
+ putMVar block ()
diff --git a/libraries/base/Control/Concurrent/QSemN.hs b/libraries/base/Control/Concurrent/QSemN.hs
new file mode 100644
index 0000000000..da5aa4466a
--- /dev/null
+++ b/libraries/base/Control/Concurrent/QSemN.hs
@@ -0,0 +1,60 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Concurrent.QSemN
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: QSemN.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Quantity semaphores
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent.QSemN
+ ( QSemN, -- abstract
+ newQSemN, -- :: Int -> IO QSemN
+ waitQSemN, -- :: QSemN -> Int -> IO ()
+ signalQSemN -- :: QSemN -> Int -> IO ()
+ ) where
+
+import Prelude
+
+import Control.Concurrent.MVar
+
+newtype QSemN = QSemN (MVar (Int,[(Int,MVar ())]))
+
+newQSemN :: Int -> IO QSemN
+newQSemN init = do
+ sem <- newMVar (init,[])
+ return (QSemN sem)
+
+waitQSemN :: QSemN -> Int -> IO ()
+waitQSemN (QSemN sem) sz = do
+ (avail,blocked) <- takeMVar sem -- gain ex. access
+ if (avail - sz) >= 0 then
+ -- discharging 'sz' still leaves the semaphore
+ -- in an 'unblocked' state.
+ putMVar sem (avail-sz,[])
+ else do
+ block <- newEmptyMVar
+ putMVar sem (avail, blocked++[(sz,block)])
+ takeMVar block
+
+signalQSemN :: QSemN -> Int -> IO ()
+signalQSemN (QSemN sem) n = do
+ (avail,blocked) <- takeMVar sem
+ (avail',blocked') <- free (avail+n) blocked
+ putMVar sem (avail',blocked')
+ where
+ free avail [] = return (avail,[])
+ free avail ((req,block):blocked)
+ | avail >= req = do
+ putMVar block ()
+ free (avail-req) blocked
+ | otherwise = do
+ (avail',blocked') <- free avail blocked
+ return (avail',(req,block):blocked')
diff --git a/libraries/base/Control/Concurrent/SampleVar.hs b/libraries/base/Control/Concurrent/SampleVar.hs
new file mode 100644
index 0000000000..e3d334108b
--- /dev/null
+++ b/libraries/base/Control/Concurrent/SampleVar.hs
@@ -0,0 +1,98 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Concurrent.SampleVar
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: SampleVar.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Sample variables
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent.SampleVar
+ (
+ SampleVar, -- :: type _ =
+
+ newEmptySampleVar, -- :: IO (SampleVar a)
+ newSampleVar, -- :: a -> IO (SampleVar a)
+ emptySampleVar, -- :: SampleVar a -> IO ()
+ readSampleVar, -- :: SampleVar a -> IO a
+ writeSampleVar -- :: SampleVar a -> a -> IO ()
+
+ ) where
+
+import Prelude
+
+import Control.Concurrent.MVar
+
+-- Sample variables are slightly different from a normal MVar:
+--
+-- * Reading an empty SampleVar causes the reader to block.
+-- (same as takeMVar on empty MVar)
+--
+-- * Reading a filled SampleVar empties it and returns value.
+-- (same as takeMVar)
+--
+-- * Writing to an empty SampleVar fills it with a value, and
+-- potentially, wakes up a blocked reader (same as for putMVar on
+-- empty MVar).
+--
+-- * Writing to a filled SampleVar overwrites the current value.
+-- (different from putMVar on full MVar.)
+
+type SampleVar a
+ = MVar (Int, -- 1 == full
+ -- 0 == empty
+ -- <0 no of readers blocked
+ MVar a)
+
+-- Initally, a SampleVar is empty/unfilled.
+
+newEmptySampleVar :: IO (SampleVar a)
+newEmptySampleVar = do
+ v <- newEmptyMVar
+ newMVar (0,v)
+
+newSampleVar :: a -> IO (SampleVar a)
+newSampleVar a = do
+ v <- newEmptyMVar
+ putMVar v a
+ newMVar (1,v)
+
+emptySampleVar :: SampleVar a -> IO ()
+emptySampleVar v = do
+ (readers, var) <- takeMVar v
+ if readers >= 0 then
+ putMVar v (0,var)
+ else
+ putMVar v (readers,var)
+
+--
+-- filled => make empty and grab sample
+-- not filled => try to grab value, empty when read val.
+--
+readSampleVar :: SampleVar a -> IO a
+readSampleVar svar = do
+ (readers,val) <- takeMVar svar
+ putMVar svar (readers-1,val)
+ takeMVar val
+
+--
+-- filled => overwrite
+-- not filled => fill, write val
+--
+writeSampleVar :: SampleVar a -> a -> IO ()
+writeSampleVar svar v = do
+ (readers,val) <- takeMVar svar
+ case readers of
+ 1 ->
+ swapMVar val v >>
+ putMVar svar (1,val)
+ _ ->
+ putMVar val v >>
+ putMVar svar (min 1 (readers+1), val)
diff --git a/libraries/base/Control/Exception.hs b/libraries/base/Control/Exception.hs
new file mode 100644
index 0000000000..444ac876f6
--- /dev/null
+++ b/libraries/base/Control/Exception.hs
@@ -0,0 +1,226 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Exception
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Exception.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-- The External API for exceptions. The functions provided in this
+-- module allow catching of exceptions in the IO monad.
+--
+-----------------------------------------------------------------------------
+
+module Control.Exception (
+
+ Exception(..), -- instance Eq, Ord, Show, Typeable
+ IOException, -- instance Eq, Ord, Show, Typeable
+ ArithException(..), -- instance Eq, Ord, Show, Typeable
+ ArrayException(..), -- instance Eq, Ord, Show, Typeable
+ AsyncException(..), -- instance Eq, Ord, Show, Typeable
+
+ try, -- :: IO a -> IO (Either Exception a)
+ tryJust, -- :: (Exception -> Maybe b) -> a -> IO (Either b a)
+
+ catch, -- :: IO a -> (Exception -> IO a) -> IO a
+ catchJust, -- :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
+
+ evaluate, -- :: a -> IO a
+
+ -- Exception predicates (for catchJust, tryJust)
+
+ ioErrors, -- :: Exception -> Maybe IOError
+ arithExceptions, -- :: Exception -> Maybe ArithException
+ errorCalls, -- :: Exception -> Maybe String
+ dynExceptions, -- :: Exception -> Maybe Dynamic
+ assertions, -- :: Exception -> Maybe String
+ asyncExceptions, -- :: Exception -> Maybe AsyncException
+ userErrors, -- :: Exception -> Maybe String
+
+ -- Throwing exceptions
+
+ throw, -- :: Exception -> a
+#ifndef __STGHUGS__
+ -- for now
+ throwTo, -- :: ThreadId -> Exception -> a
+#endif
+
+ -- Dynamic exceptions
+
+ throwDyn, -- :: Typeable ex => ex -> b
+ throwDynTo, -- :: Typeable ex => ThreadId -> ex -> b
+ catchDyn, -- :: Typeable ex => IO a -> (ex -> IO a) -> IO a
+
+ -- Async exception control
+
+ block, -- :: IO a -> IO a
+ unblock, -- :: IO a -> IO a
+
+ -- Assertions
+
+ -- for now
+ assert, -- :: Bool -> a -> a
+
+ -- Utilities
+
+ finally, -- :: IO a -> IO b -> IO b
+
+ bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO ()
+ bracket_, -- :: IO a -> IO b -> IO c -> IO ()
+
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import Prelude hiding (catch)
+import GHC.Prim ( assert )
+import GHC.Exception hiding (try, catch, bracket, bracket_)
+import GHC.Conc ( throwTo, ThreadId )
+import GHC.IOBase ( IO(..) )
+#endif
+
+#ifdef __HUGS__
+import Prelude hiding ( catch )
+import PrelPrim ( catchException
+ , Exception(..)
+ , throw
+ , ArithException(..)
+ , AsyncException(..)
+ , assert
+ )
+#endif
+
+import Data.Dynamic
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(Exception,exceptionTc,"Exception")
+INSTANCE_TYPEABLE0(IOException,ioExceptionTc,"IOException")
+INSTANCE_TYPEABLE0(ArithException,arithExceptionTc,"ArithException")
+INSTANCE_TYPEABLE0(ArrayException,arrayExceptionTc,"ArrayException")
+INSTANCE_TYPEABLE0(AsyncException,asyncExceptionTc,"AsyncException")
+
+-----------------------------------------------------------------------------
+-- Catching exceptions
+
+-- PrelException defines 'catchException' for us.
+
+catch :: IO a -> (Exception -> IO a) -> IO a
+catch = catchException
+
+catchJust :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
+catchJust p a handler = catch a handler'
+ where handler' e = case p e of
+ Nothing -> throw e
+ Just b -> handler b
+
+-----------------------------------------------------------------------------
+-- evaluate
+
+evaluate :: a -> IO a
+evaluate a = a `seq` return a
+
+-----------------------------------------------------------------------------
+-- 'try' and variations.
+
+try :: IO a -> IO (Either Exception a)
+try a = catch (a >>= \ v -> return (Right v)) (\e -> return (Left e))
+
+tryJust :: (Exception -> Maybe b) -> IO a -> IO (Either b a)
+tryJust p a = do
+ r <- try a
+ case r of
+ Right v -> return (Right v)
+ Left e -> case p e of
+ Nothing -> throw e
+ Just b -> return (Left b)
+
+-----------------------------------------------------------------------------
+-- Dynamic exception types. Since one of the possible kinds of exception
+-- is a dynamically typed value, we can effectively have polymorphic
+-- exceptions.
+
+-- throwDyn will raise any value as an exception, provided it is in the
+-- Typeable class (see Dynamic.lhs).
+
+-- catchDyn will catch any exception of a given type (determined by the
+-- handler function). Any raised exceptions that don't match are
+-- re-raised.
+
+throwDyn :: Typeable exception => exception -> b
+throwDyn exception = throw (DynException (toDyn exception))
+
+throwDynTo :: Typeable exception => ThreadId -> exception -> IO ()
+throwDynTo t exception = throwTo t (DynException (toDyn exception))
+
+catchDyn :: Typeable exception => IO a -> (exception -> IO a) -> IO a
+catchDyn m k = catchException m handle
+ where handle ex = case ex of
+ (DynException dyn) ->
+ case fromDynamic dyn of
+ Just exception -> k exception
+ Nothing -> throw ex
+ _ -> throw ex
+
+-----------------------------------------------------------------------------
+-- Exception Predicates
+
+ioErrors :: Exception -> Maybe IOError
+arithExceptions :: Exception -> Maybe ArithException
+errorCalls :: Exception -> Maybe String
+dynExceptions :: Exception -> Maybe Dynamic
+assertions :: Exception -> Maybe String
+asyncExceptions :: Exception -> Maybe AsyncException
+userErrors :: Exception -> Maybe String
+
+ioErrors e@(IOException _) = Just e
+ioErrors _ = Nothing
+
+arithExceptions (ArithException e) = Just e
+arithExceptions _ = Nothing
+
+errorCalls (ErrorCall e) = Just e
+errorCalls _ = Nothing
+
+assertions (AssertionFailed e) = Just e
+assertions _ = Nothing
+
+dynExceptions (DynException e) = Just e
+dynExceptions _ = Nothing
+
+asyncExceptions (AsyncException e) = Just e
+asyncExceptions _ = Nothing
+
+userErrors (UserError e) = Just e
+userErrors _ = Nothing
+
+-----------------------------------------------------------------------------
+-- Some Useful Functions
+
+bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+bracket before after thing =
+ block (do
+ a <- before
+ r <- catch
+ (unblock (thing a))
+ (\e -> do { after a; throw e })
+ after a
+ return r
+ )
+
+-- finally is an instance of bracket, but it's quite common
+-- so we give the specialised version for efficiency.
+finally :: IO a -> IO b -> IO a
+a `finally` sequel =
+ block (do
+ r <- catch
+ (unblock a)
+ (\e -> do { sequel; throw e })
+ sequel
+ return r
+ )
+
+bracket_ :: IO a -> IO b -> IO c -> IO c
+bracket_ before after thing = bracket before (const after) (const thing)
diff --git a/libraries/base/Control/Monad.hs b/libraries/base/Control/Monad.hs
new file mode 100644
index 0000000000..d2e9908826
--- /dev/null
+++ b/libraries/base/Control/Monad.hs
@@ -0,0 +1,160 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Monad.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad
+ ( MonadPlus ( -- class context: Monad
+ mzero -- :: (MonadPlus m) => m a
+ , mplus -- :: (MonadPlus m) => m a -> m a -> m a
+ )
+ , join -- :: (Monad m) => m (m a) -> m a
+ , guard -- :: (MonadPlus m) => Bool -> m ()
+ , when -- :: (Monad m) => Bool -> m () -> m ()
+ , unless -- :: (Monad m) => Bool -> m () -> m ()
+ , ap -- :: (Monad m) => m (a -> b) -> m a -> m b
+ , msum -- :: (MonadPlus m) => [m a] -> m a
+ , filterM -- :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
+ , mapAndUnzipM -- :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
+ , zipWithM -- :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ , zipWithM_ -- :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()
+ , foldM -- :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
+
+ , liftM -- :: (Monad m) => (a -> b) -> (m a -> m b)
+ , liftM2 -- :: (Monad m) => (a -> b -> c) -> (m a -> m b -> m c)
+ , liftM3 -- :: ...
+ , liftM4 -- :: ...
+ , liftM5 -- :: ...
+
+ , Monad((>>=), (>>), return, fail)
+ , Functor(fmap)
+
+ , mapM -- :: (Monad m) => (a -> m b) -> [a] -> m [b]
+ , mapM_ -- :: (Monad m) => (a -> m b) -> [a] -> m ()
+ , sequence -- :: (Monad m) => [m a] -> m [a]
+ , sequence_ -- :: (Monad m) => [m a] -> m ()
+ , (=<<) -- :: (Monad m) => (a -> m b) -> m a -> m b
+ ) where
+
+import Data.Maybe
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.List
+import GHC.Base
+#endif
+
+infixr 1 =<<
+
+-- -----------------------------------------------------------------------------
+-- Prelude monad functions
+
+{-# SPECIALISE (=<<) :: (a -> [b]) -> [a] -> [b] #-}
+(=<<) :: Monad m => (a -> m b) -> m a -> m b
+f =<< x = x >>= f
+
+sequence :: Monad m => [m a] -> m [a]
+{-# INLINE sequence #-}
+sequence ms = foldr k (return []) ms
+ where
+ k m m' = do { x <- m; xs <- m'; return (x:xs) }
+
+sequence_ :: Monad m => [m a] -> m ()
+{-# INLINE sequence_ #-}
+sequence_ ms = foldr (>>) (return ()) ms
+
+mapM :: Monad m => (a -> m b) -> [a] -> m [b]
+{-# INLINE mapM #-}
+mapM f as = sequence (map f as)
+
+mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
+{-# INLINE mapM_ #-}
+mapM_ f as = sequence_ (map f as)
+
+-- -----------------------------------------------------------------------------
+-- Monadic classes: MonadPlus
+
+class Monad m => MonadPlus m where
+ mzero :: m a
+ mplus :: m a -> m a -> m a
+
+instance MonadPlus [] where
+ mzero = []
+ mplus = (++)
+
+instance MonadPlus Maybe where
+ mzero = Nothing
+
+ Nothing `mplus` ys = ys
+ xs `mplus` _ys = xs
+
+-- -----------------------------------------------------------------------------
+-- Functions mandated by the Prelude
+
+guard :: (MonadPlus m) => Bool -> m ()
+guard True = return ()
+guard False = mzero
+
+-- This subsumes the list-based filter function.
+
+filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
+filterM _ [] = return []
+filterM p (x:xs) = do
+ flg <- p x
+ ys <- filterM p xs
+ return (if flg then x:ys else ys)
+
+-- This subsumes the list-based concat function.
+
+msum :: MonadPlus m => [m a] -> m a
+{-# INLINE msum #-}
+msum = foldr mplus mzero
+
+-- -----------------------------------------------------------------------------
+-- Other monad functions
+
+join :: (Monad m) => m (m a) -> m a
+join x = x >>= id
+
+mapAndUnzipM :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
+mapAndUnzipM f xs = sequence (map f xs) >>= return . unzip
+
+zipWithM :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
+zipWithM f xs ys = sequence (zipWith f xs ys)
+
+zipWithM_ :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()
+zipWithM_ f xs ys = sequence_ (zipWith f xs ys)
+
+foldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
+foldM _ a [] = return a
+foldM f a (x:xs) = f a x >>= \fax -> foldM f fax xs
+
+unless :: (Monad m) => Bool -> m () -> m ()
+unless p s = if p then return () else s
+
+when :: (Monad m) => Bool -> m () -> m ()
+when p s = if p then s else return ()
+
+ap :: (Monad m) => m (a -> b) -> m a -> m b
+ap = liftM2 id
+
+liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r
+liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
+liftM3 :: (Monad m) => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
+liftM4 :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
+liftM5 :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
+
+liftM f m1 = do { x1 <- m1; return (f x1) }
+liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
+liftM3 f m1 m2 m3 = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }
+liftM4 f m1 m2 m3 m4 = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; return (f x1 x2 x3 x4) }
+liftM5 f m1 m2 m3 m4 m5 = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; x5 <- m5; return (f x1 x2 x3 x4 x5) }
diff --git a/libraries/base/Control/Monad/Cont.hs b/libraries/base/Control/Monad/Cont.hs
new file mode 100644
index 0000000000..541f6a6df4
--- /dev/null
+++ b/libraries/base/Control/Monad/Cont.hs
@@ -0,0 +1,122 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Cont
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Cont.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Continuation monads.
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.Cont (
+ MonadCont(..),
+ Cont(..),
+ runCont,
+ mapCont,
+ withCont,
+ ContT(..),
+ runContT,
+ mapContT,
+ withContT,
+ module Control.Monad,
+ module Control.Monad.Trans,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Trans
+import Control.Monad.Reader
+import Control.Monad.Writer
+import Control.Monad.State
+import Control.Monad.RWS
+
+class (Monad m) => MonadCont m where
+ callCC :: ((a -> m b) -> m a) -> m a
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable continuation monad
+
+newtype Cont r a = Cont { runCont :: (a -> r) -> r }
+
+instance Functor (Cont r) where
+ fmap f m = Cont $ \c -> runCont m (c . f)
+
+instance Monad (Cont r) where
+ return a = Cont ($ a)
+ m >>= k = Cont $ \c -> runCont m $ \a -> runCont (k a) c
+
+instance MonadCont (Cont r) where
+ callCC f = Cont $ \c -> runCont (f (\a -> Cont $ \_ -> c a)) c
+
+mapCont :: (r -> r) -> Cont r a -> Cont r a
+mapCont f m = Cont $ f . runCont m
+
+withCont :: ((b -> r) -> (a -> r)) -> Cont r a -> Cont r b
+withCont f m = Cont $ runCont m . f
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable continuation monad, with an inner monad
+
+newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }
+
+instance (Monad m) => Functor (ContT r m) where
+ fmap f m = ContT $ \c -> runContT m (c . f)
+
+instance (Monad m) => Monad (ContT r m) where
+ return a = ContT ($ a)
+ m >>= k = ContT $ \c -> runContT m (\a -> runContT (k a) c)
+
+instance (Monad m) => MonadCont (ContT r m) where
+ callCC f = ContT $ \c -> runContT (f (\a -> ContT $ \_ -> c a)) c
+
+instance MonadTrans (ContT r) where
+ lift m = ContT (m >>=)
+
+instance (MonadIO m) => MonadIO (ContT r m) where
+ liftIO = lift . liftIO
+
+instance (MonadReader r' m) => MonadReader r' (ContT r m) where
+ ask = lift ask
+ local f m = ContT $ \c -> do
+ r <- ask
+ local f (runContT m (local (const r) . c))
+
+instance (MonadState s m) => MonadState s (ContT r m) where
+ get = lift get
+ put = lift . put
+
+-- -----------------------------------------------------------------------------
+-- MonadCont instances for other monad transformers
+
+instance (MonadCont m) => MonadCont (ReaderT r m) where
+ callCC f = ReaderT $ \r ->
+ callCC $ \c ->
+ runReaderT (f (\a -> ReaderT $ \_ -> c a)) r
+
+instance (MonadCont m) => MonadCont (StateT s m) where
+ callCC f = StateT $ \s ->
+ callCC $ \c ->
+ runStateT (f (\a -> StateT $ \s' -> c (a, s'))) s
+
+instance (Monoid w, MonadCont m) => MonadCont (WriterT w m) where
+ callCC f = WriterT $
+ callCC $ \c ->
+ runWriterT (f (\a -> WriterT $ c (a, mempty)))
+
+instance (Monoid w, MonadCont m) => MonadCont (RWST r w s m) where
+ callCC f = RWST $ \r s ->
+ callCC $ \c ->
+ runRWST (f (\a -> RWST $ \_ s' -> c (a, s', mempty))) r s
+
+mapContT :: (m r -> m r) -> ContT r m a -> ContT r m a
+mapContT f m = ContT $ f . runContT m
+
+withContT :: ((b -> m r) -> (a -> m r)) -> ContT r m a -> ContT r m b
+withContT f m = ContT $ runContT m . f
diff --git a/libraries/base/Control/Monad/Error.hs b/libraries/base/Control/Monad/Error.hs
new file mode 100644
index 0000000000..979ae35b4c
--- /dev/null
+++ b/libraries/base/Control/Monad/Error.hs
@@ -0,0 +1,224 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Error
+-- Copyright : (c) Michael Weber <michael.weber@post.rwth-aachen.de>, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable (reqruires multi-param type classes)
+--
+-- $Id: Error.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Error monad.
+--
+-- Rendered by Michael Weber <michael.weber@post.rwth-aachen.de>,
+-- inspired by the Haskell Monad Template Library from
+-- \A[HREF="http://www.cse.ogi.edu/~andy"]{Andy Gill}}
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.Error (
+ Error(..),
+ MonadError(..),
+ ErrorT(..),
+ runErrorT,
+ mapErrorT,
+ module Control.Monad,
+ module Control.Monad.Fix,
+ module Control.Monad.Trans,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Fix
+import Control.Monad.Trans
+import Control.Monad.Reader
+import Control.Monad.Writer
+import Control.Monad.State
+import Control.Monad.RWS
+import Control.Monad.Cont
+
+import System.IO
+
+-- ---------------------------------------------------------------------------
+-- class MonadError
+--
+-- throws an exception inside the monad and thus interrupts
+-- normal execution order, until an error handler is reached}
+--
+-- catches an exception inside the monad (that was previously
+-- thrown by throwError
+
+class Error a where
+ noMsg :: a
+ strMsg :: String -> a
+
+ noMsg = strMsg ""
+ strMsg _ = noMsg
+
+instance Error [Char] where
+ noMsg = ""
+ strMsg = id
+
+instance Error IOError where
+ strMsg = userError
+
+class (Monad m) => MonadError e m | m -> e where
+ throwError :: e -> m a
+ catchError :: m a -> (e -> m a) -> m a
+
+instance MonadPlus IO where
+ mzero = ioError (userError "mzero")
+ m `mplus` n = m `catch` \_ -> n
+
+instance MonadError IOError IO where
+ throwError = ioError
+ catchError = catch
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable error monad
+
+instance Functor (Either e) where
+ fmap _ (Left l) = Left l
+ fmap f (Right r) = Right (f r)
+
+instance (Error e) => Monad (Either e) where
+ return = Right
+ Left l >>= _ = Left l
+ Right r >>= k = k r
+ fail msg = Left (strMsg msg)
+
+instance (Error e) => MonadPlus (Either e) where
+ mzero = Left noMsg
+ Left _ `mplus` n = n
+ m `mplus` _ = m
+
+instance (Error e) => MonadFix (Either e) where
+ mfix f = let
+ a = f $ case a of
+ Right r -> r
+ _ -> error "empty mfix argument"
+ in a
+
+instance (Error e) => MonadError e (Either e) where
+ throwError = Left
+ Left l `catchError` h = h l
+ Right r `catchError` _ = Right r
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable error monad, with an inner monad
+
+newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }
+
+-- The ErrorT Monad structure is parameterized over two things:
+-- * e - The error type.
+-- * m - The inner monad.
+
+-- Here are some examples of use:
+--
+-- type ErrorWithIO e a = ErrorT e IO a
+-- ==> ErrorT (IO (Either e a))
+--
+-- type ErrorAndStateWithIO e s a = ErrorT e (StateT s IO) a
+-- ==> ErrorT (StateT s IO (Either e a))
+-- ==> ErrorT (StateT (s -> IO (Either e a,s)))
+--
+
+instance (Monad m) => Functor (ErrorT e m) where
+ fmap f m = ErrorT $ do
+ a <- runErrorT m
+ case a of
+ Left l -> return (Left l)
+ Right r -> return (Right (f r))
+
+instance (Monad m, Error e) => Monad (ErrorT e m) where
+ return a = ErrorT $ return (Right a)
+ m >>= k = ErrorT $ do
+ a <- runErrorT m
+ case a of
+ Left l -> return (Left l)
+ Right r -> runErrorT (k r)
+ fail msg = ErrorT $ return (Left (strMsg msg))
+
+instance (Monad m, Error e) => MonadPlus (ErrorT e m) where
+ mzero = ErrorT $ return (Left noMsg)
+ m `mplus` n = ErrorT $ do
+ a <- runErrorT m
+ case a of
+ Left _ -> runErrorT n
+ Right r -> return (Right r)
+
+instance (MonadFix m, Error e) => MonadFix (ErrorT e m) where
+ mfix f = ErrorT $ mfix $ \a -> runErrorT $ f $ case a of
+ Right r -> r
+ _ -> error "empty mfix argument"
+
+instance (Monad m, Error e) => MonadError e (ErrorT e m) where
+ throwError l = ErrorT $ return (Left l)
+ m `catchError` h = ErrorT $ do
+ a <- runErrorT m
+ case a of
+ Left l -> runErrorT (h l)
+ Right r -> return (Right r)
+
+instance (Error e) => MonadTrans (ErrorT e) where
+ lift m = ErrorT $ do
+ a <- m
+ return (Right a)
+
+instance (Error e, MonadIO m) => MonadIO (ErrorT e m) where
+ liftIO = lift . liftIO
+
+instance (Error e, MonadReader r m) => MonadReader r (ErrorT e m) where
+ ask = lift ask
+ local f m = ErrorT $ local f (runErrorT m)
+
+instance (Error e, MonadWriter w m) => MonadWriter w (ErrorT e m) where
+ tell = lift . tell
+ listen m = ErrorT $ do
+ (a, w) <- listen (runErrorT m)
+ return $ case a of
+ Left l -> Left l
+ Right r -> Right (r, w)
+ pass m = ErrorT $ pass $ do
+ a <- runErrorT m
+ return $ case a of
+ Left l -> (Left l, id)
+ Right (r, f) -> (Right r, f)
+
+instance (Error e, MonadState s m) => MonadState s (ErrorT e m) where
+ get = lift get
+ put = lift . put
+
+instance (Error e, MonadCont m) => MonadCont (ErrorT e m) where
+ callCC f = ErrorT $
+ callCC $ \c ->
+ runErrorT (f (\a -> ErrorT $ c (Right a)))
+
+mapErrorT :: (m (Either e a) -> n (Either e' b)) -> ErrorT e m a -> ErrorT e' n b
+mapErrorT f m = ErrorT $ f (runErrorT m)
+
+-- ---------------------------------------------------------------------------
+-- MonadError instances for other monad transformers
+
+instance (MonadError e m) => MonadError e (ReaderT r m) where
+ throwError = lift . throwError
+ m `catchError` h = ReaderT $ \r -> runReaderT m r
+ `catchError` \e -> runReaderT (h e) r
+
+instance (Monoid w, MonadError e m) => MonadError e (WriterT w m) where
+ throwError = lift . throwError
+ m `catchError` h = WriterT $ runWriterT m
+ `catchError` \e -> runWriterT (h e)
+
+instance (MonadError e m) => MonadError e (StateT s m) where
+ throwError = lift . throwError
+ m `catchError` h = StateT $ \s -> runStateT m s
+ `catchError` \e -> runStateT (h e) s
+
+instance (Monoid w, MonadError e m) => MonadError e (RWST r w s m) where
+ throwError = lift . throwError
+ m `catchError` h = RWST $ \r s -> runRWST m r s
+ `catchError` \e -> runRWST (h e) r s
diff --git a/libraries/base/Control/Monad/Fix.hs b/libraries/base/Control/Monad/Fix.hs
new file mode 100644
index 0000000000..a596f445fc
--- /dev/null
+++ b/libraries/base/Control/Monad/Fix.hs
@@ -0,0 +1,55 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Fix
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable (reqruires multi-param type classes)
+--
+-- $Id: Fix.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Fix monad.
+--
+-- Inspired by the paper:
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.Fix (
+ MonadFix(
+ mfix -- :: (a -> m a) -> m a
+ ),
+ fix -- :: (a -> a) -> a
+ ) where
+
+import Prelude
+
+import System.IO
+import Control.Monad.ST
+
+
+fix :: (a -> a) -> a
+fix f = let x = f x in x
+
+class (Monad m) => MonadFix m where
+ mfix :: (a -> m a) -> m a
+
+-- Perhaps these should live beside (the ST & IO) definition.
+instance MonadFix IO where
+ mfix = fixIO
+
+instance MonadFix (ST s) where
+ mfix = fixST
+
+instance MonadFix Maybe where
+ mfix f = let
+ a = f $ case a of
+ Just x -> x
+ _ -> error "empty mfix argument"
+ in a
diff --git a/libraries/base/Control/Monad/Identity.hs b/libraries/base/Control/Monad/Identity.hs
new file mode 100644
index 0000000000..aee6f031da
--- /dev/null
+++ b/libraries/base/Control/Monad/Identity.hs
@@ -0,0 +1,63 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Identity
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : portable
+--
+-- $Id: Identity.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Identity monad.
+--
+-- Inspired by the paper:
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.Identity (
+ Identity(..),
+ runIdentity,
+ module Control.Monad,
+ module Control.Monad.Fix,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Fix
+
+-- ---------------------------------------------------------------------------
+-- Identity wrapper
+--
+-- Abstraction for wrapping up a object.
+-- If you have an monadic function, say:
+--
+-- example :: Int -> IdentityMonad Int
+-- example x = return (x*x)
+--
+-- you can "run" it, using
+--
+-- Main> runIdentity (example 42)
+-- 1764 :: Int
+
+newtype Identity a = Identity { runIdentity :: a }
+
+-- ---------------------------------------------------------------------------
+-- Identity instances for Functor and Monad
+
+instance Functor Identity where
+ fmap f m = Identity (f (runIdentity m))
+
+instance Monad Identity where
+ return a = Identity a
+ m >>= k = k (runIdentity m)
+
+instance MonadFix Identity where
+ mfix f = Identity (fix (runIdentity . f))
diff --git a/libraries/base/Control/Monad/List.hs b/libraries/base/Control/Monad/List.hs
new file mode 100644
index 0000000000..e6c7daa23a
--- /dev/null
+++ b/libraries/base/Control/Monad/List.hs
@@ -0,0 +1,87 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.List
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable ( requires mulit-parameter type classes )
+--
+-- $Id: List.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The List monad.
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.List (
+ ListT(..),
+ runListT,
+ mapListT,
+ module Control.Monad,
+ module Control.Monad.Trans,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Trans
+import Control.Monad.Reader
+import Control.Monad.State
+import Control.Monad.Cont
+import Control.Monad.Error
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable list monad, with an inner monad
+
+newtype ListT m a = ListT { runListT :: m [a] }
+
+instance (Monad m) => Functor (ListT m) where
+ fmap f m = ListT $ do
+ a <- runListT m
+ return (map f a)
+
+instance (Monad m) => Monad (ListT m) where
+ return a = ListT $ return [a]
+ m >>= k = ListT $ do
+ a <- runListT m
+ b <- mapM (runListT . k) a
+ return (concat b)
+ fail _ = ListT $ return []
+
+instance (Monad m) => MonadPlus (ListT m) where
+ mzero = ListT $ return []
+ m `mplus` n = ListT $ do
+ a <- runListT m
+ b <- runListT n
+ return (a ++ b)
+
+instance MonadTrans ListT where
+ lift m = ListT $ do
+ a <- m
+ return [a]
+
+instance (MonadIO m) => MonadIO (ListT m) where
+ liftIO = lift . liftIO
+
+instance (MonadReader s m) => MonadReader s (ListT m) where
+ ask = lift ask
+ local f m = ListT $ local f (runListT m)
+
+instance (MonadState s m) => MonadState s (ListT m) where
+ get = lift get
+ put = lift . put
+
+instance (MonadCont m) => MonadCont (ListT m) where
+ callCC f = ListT $
+ callCC $ \c ->
+ runListT (f (\a -> ListT $ c [a]))
+
+instance (MonadError e m) => MonadError e (ListT m) where
+ throwError = lift . throwError
+ m `catchError` h = ListT $ runListT m
+ `catchError` \e -> runListT (h e)
+
+mapListT :: (m [a] -> n [b]) -> ListT m a -> ListT n b
+mapListT f m = ListT $ f (runListT m)
diff --git a/libraries/base/Control/Monad/Monoid.hs b/libraries/base/Control/Monad/Monoid.hs
new file mode 100644
index 0000000000..e81b2be798
--- /dev/null
+++ b/libraries/base/Control/Monad/Monoid.hs
@@ -0,0 +1,58 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Monoid
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable ( requires mulit-parameter type classes )
+--
+-- $Id: Monoid.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Declaration of the Monoid class,and instances for list and functions
+--
+-- Inspired by the paper
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+-----------------------------------------------------------------------------
+
+module Control.Monad.Monoid (
+ Monoid(..)
+ ) where
+
+import Prelude
+
+-- ---------------------------------------------------------------------------
+-- The Monoid class
+
+class Monoid a where
+ mempty :: a
+ mappend :: a -> a -> a
+ mconcat :: [a] -> a
+
+-- Now the default for mconcat. For most types, this
+-- default will be used, but is included in the class definition so
+-- that optimized version of mconcat can be provided
+-- for specific types.
+
+ mconcat = foldr mappend mempty
+
+-- Monoid instances.
+
+instance Monoid [a] where
+ mempty = []
+ mappend = (++)
+
+instance Monoid (a -> a) where
+ mempty = id
+ mappend = (.)
+
+instance Monoid () where
+ -- Should it be strict?
+ mempty = ()
+ _ `mappend` _ = ()
+ mconcat _ = ()
diff --git a/libraries/base/Control/Monad/RWS.hs b/libraries/base/Control/Monad/RWS.hs
new file mode 100644
index 0000000000..26d624d0e4
--- /dev/null
+++ b/libraries/base/Control/Monad/RWS.hs
@@ -0,0 +1,170 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.RWS
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable ( requires mulit-parameter type classes,
+-- requires functional dependencies )
+--
+-- $Id: RWS.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Declaration of the MonadRWS class.
+--
+-- Inspired by the paper
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+-----------------------------------------------------------------------------
+
+module Control.Monad.RWS (
+ RWS(..),
+ runRWS,
+ evalRWS,
+ execRWS,
+ mapRWS,
+ withRWS,
+ RWST(..),
+ runRWST,
+ evalRWST,
+ execRWST,
+ mapRWST,
+ withRWST,
+ module Control.Monad,
+ module Control.Monad.Fix,
+ module Control.Monad.Trans,
+ module Control.Monad.Reader,
+ module Control.Monad.Writer,
+ module Control.Monad.State,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Monoid
+import Control.Monad.Fix
+import Control.Monad.Trans
+import Control.Monad.Reader
+import Control.Monad.Writer
+import Control.Monad.State
+
+
+newtype RWS r w s a = RWS { runRWS :: r -> s -> (a, s, w) }
+
+instance Functor (RWS r w s) where
+ fmap f m = RWS $ \r s -> let
+ (a, s', w) = runRWS m r s
+ in (f a, s', w)
+
+instance (Monoid w) => Monad (RWS r w s) where
+ return a = RWS $ \_ s -> (a, s, mempty)
+ m >>= k = RWS $ \r s -> let
+ (a, s', w) = runRWS m r s
+ (b, s'', w') = runRWS (k a) r s'
+ in (b, s'', w `mappend` w')
+
+instance (Monoid w) => MonadFix (RWS r w s) where
+ mfix f = RWS $ \r s -> let (a, s', w) = runRWS (f a) r s in (a, s', w)
+
+instance (Monoid w) => MonadReader r (RWS r w s) where
+ ask = RWS $ \r s -> (r, s, mempty)
+ local f m = RWS $ \r s -> runRWS m (f r) s
+
+instance (Monoid w) => MonadWriter w (RWS r w s) where
+ tell w = RWS $ \_ s -> ((), s, w)
+ listen m = RWS $ \r s -> let
+ (a, s', w) = runRWS m r s
+ in ((a, w), s', w)
+ pass m = RWS $ \r s -> let
+ ((a, f), s', w) = runRWS m r s
+ in (a, s', f w)
+
+instance (Monoid w) => MonadState s (RWS r w s) where
+ get = RWS $ \_ s -> (s, s, mempty)
+ put s = RWS $ \_ _ -> ((), s, mempty)
+
+
+evalRWS :: RWS r w s a -> r -> s -> (a, w)
+evalRWS m r s = let
+ (a, _, w) = runRWS m r s
+ in (a, w)
+
+execRWS :: RWS r w s a -> r -> s -> (s, w)
+execRWS m r s = let
+ (_, s', w) = runRWS m r s
+ in (s', w)
+
+mapRWS :: ((a, s, w) -> (b, s, w')) -> RWS r w s a -> RWS r w' s b
+mapRWS f m = RWS $ \r s -> f (runRWS m r s)
+
+withRWS :: (r' -> s -> (r, s)) -> RWS r w s a -> RWS r' w s a
+withRWS f m = RWS $ \r s -> uncurry (runRWS m) (f r s)
+
+
+newtype RWST r w s m a = RWST { runRWST :: r -> s -> m (a, s, w) }
+
+instance (Monad m) => Functor (RWST r w s m) where
+ fmap f m = RWST $ \r s -> do
+ (a, s', w) <- runRWST m r s
+ return (f a, s', w)
+
+instance (Monoid w, Monad m) => Monad (RWST r w s m) where
+ return a = RWST $ \_ s -> return (a, s, mempty)
+ m >>= k = RWST $ \r s -> do
+ (a, s', w) <- runRWST m r s
+ (b, s'',w') <- runRWST (k a) r s'
+ return (b, s'', w `mappend` w')
+ fail msg = RWST $ \_ _ -> fail msg
+
+instance (Monoid w, MonadPlus m) => MonadPlus (RWST r w s m) where
+ mzero = RWST $ \_ _ -> mzero
+ m `mplus` n = RWST $ \r s -> runRWST m r s `mplus` runRWST n r s
+
+instance (Monoid w, MonadFix m) => MonadFix (RWST r w s m) where
+ mfix f = RWST $ \r s -> mfix $ \ ~(a, _, _) -> runRWST (f a) r s
+
+instance (Monoid w, Monad m) => MonadReader r (RWST r w s m) where
+ ask = RWST $ \r s -> return (r, s, mempty)
+ local f m = RWST $ \r s -> runRWST m (f r) s
+
+instance (Monoid w, Monad m) => MonadWriter w (RWST r w s m) where
+ tell w = RWST $ \_ s -> return ((),s,w)
+ listen m = RWST $ \r s -> do
+ (a, s', w) <- runRWST m r s
+ return ((a, w), s', w)
+ pass m = RWST $ \r s -> do
+ ((a, f), s', w) <- runRWST m r s
+ return (a, s', f w)
+
+instance (Monoid w, Monad m) => MonadState s (RWST r w s m) where
+ get = RWST $ \_ s -> return (s, s, mempty)
+ put s = RWST $ \_ _ -> return ((), s, mempty)
+
+instance (Monoid w) => MonadTrans (RWST r w s) where
+ lift m = RWST $ \_ s -> do
+ a <- m
+ return (a, s, mempty)
+
+instance (Monoid w, MonadIO m) => MonadIO (RWST r w s m) where
+ liftIO = lift . liftIO
+
+
+evalRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (a, w)
+evalRWST m r s = do
+ (a, _, w) <- runRWST m r s
+ return (a, w)
+
+execRWST :: (Monad m) => RWST r w s m a -> r -> s -> m (s, w)
+execRWST m r s = do
+ (_, s', w) <- runRWST m r s
+ return (s', w)
+
+mapRWST :: (m (a, s, w) -> n (b, s, w')) -> RWST r w s m a -> RWST r w' s n b
+mapRWST f m = RWST $ \r s -> f (runRWST m r s)
+
+withRWST :: (r' -> s -> (r, s)) -> RWST r w s m a -> RWST r' w s m a
+withRWST f m = RWST $ \r s -> uncurry (runRWST m) (f r s)
diff --git a/libraries/base/Control/Monad/Reader.hs b/libraries/base/Control/Monad/Reader.hs
new file mode 100644
index 0000000000..d03c446aee
--- /dev/null
+++ b/libraries/base/Control/Monad/Reader.hs
@@ -0,0 +1,143 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Reader
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable ( requires mulit-parameter type classes,
+-- requires functional dependencies )
+--
+-- $Id: Reader.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Declaration of the Monoid class,and instances for list and functions
+--
+-- Inspired by the paper
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+-----------------------------------------------------------------------------
+
+module Control.Monad.Reader (
+ MonadReader(..),
+ asks,
+ Reader(..),
+ runReader,
+ mapReader,
+ withReader,
+ ReaderT(..),
+ runReaderT,
+ mapReaderT,
+ withReaderT,
+ module Control.Monad,
+ module Control.Monad.Fix,
+ module Control.Monad.Trans,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Fix
+import Control.Monad.Trans
+
+-- ----------------------------------------------------------------------------
+-- class MonadReader
+-- asks for the internal (non-mutable) state.
+
+class (Monad m) => MonadReader r m | m -> r where
+ ask :: m r
+ local :: (r -> r) -> m a -> m a
+
+-- This allows you to provide a projection function.
+
+asks :: (MonadReader r m) => (r -> a) -> m a
+asks f = do
+ r <- ask
+ return (f r)
+
+-- ----------------------------------------------------------------------------
+-- The partially applied function type is a simple reader monad
+
+instance Functor ((->) r) where
+ fmap = (.)
+
+instance Monad ((->) r) where
+ return = const
+ m >>= k = \r -> k (m r) r
+
+instance MonadFix ((->) r) where
+ mfix f = \r -> let a = f a r in a
+
+instance MonadReader r ((->) r) where
+ ask = id
+ local f m = m . f
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable reader monad
+
+newtype Reader r a = Reader { runReader :: r -> a }
+
+instance Functor (Reader r) where
+ fmap f m = Reader $ \r -> f (runReader m r)
+
+instance Monad (Reader r) where
+ return a = Reader $ \_ -> a
+ m >>= k = Reader $ \r -> runReader (k (runReader m r)) r
+
+instance MonadFix (Reader r) where
+ mfix f = Reader $ \r -> let a = runReader (f a) r in a
+
+instance MonadReader r (Reader r) where
+ ask = Reader id
+ local f m = Reader $ runReader m . f
+
+mapReader :: (a -> b) -> Reader r a -> Reader r b
+mapReader f m = Reader $ f . runReader m
+
+-- This is a more general version of local.
+
+withReader :: (r' -> r) -> Reader r a -> Reader r' a
+withReader f m = Reader $ runReader m . f
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable reader monad, with an inner monad
+
+newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
+
+instance (Monad m) => Functor (ReaderT r m) where
+ fmap f m = ReaderT $ \r -> do
+ a <- runReaderT m r
+ return (f a)
+
+instance (Monad m) => Monad (ReaderT r m) where
+ return a = ReaderT $ \_ -> return a
+ m >>= k = ReaderT $ \r -> do
+ a <- runReaderT m r
+ runReaderT (k a) r
+ fail msg = ReaderT $ \_ -> fail msg
+
+instance (MonadPlus m) => MonadPlus (ReaderT r m) where
+ mzero = ReaderT $ \_ -> mzero
+ m `mplus` n = ReaderT $ \r -> runReaderT m r `mplus` runReaderT n r
+
+instance (MonadFix m) => MonadFix (ReaderT r m) where
+ mfix f = ReaderT $ \r -> mfix $ \a -> runReaderT (f a) r
+
+instance (Monad m) => MonadReader r (ReaderT r m) where
+ ask = ReaderT return
+ local f m = ReaderT $ \r -> runReaderT m (f r)
+
+instance MonadTrans (ReaderT r) where
+ lift m = ReaderT $ \_ -> m
+
+instance (MonadIO m) => MonadIO (ReaderT r m) where
+ liftIO = lift . liftIO
+
+mapReaderT :: (m a -> n b) -> ReaderT w m a -> ReaderT w n b
+mapReaderT f m = ReaderT $ f . runReaderT m
+
+withReaderT :: (r' -> r) -> ReaderT r m a -> ReaderT r' m a
+withReaderT f m = ReaderT $ runReaderT m . f
diff --git a/libraries/base/Control/Monad/ST.hs b/libraries/base/Control/Monad/ST.hs
new file mode 100644
index 0000000000..6cbae953d3
--- /dev/null
+++ b/libraries/base/Control/Monad/ST.hs
@@ -0,0 +1,53 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.ST
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: ST.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The State Transformer Monad, ST
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.ST
+ (
+ ST -- abstract, instance of Functor, Monad, Typeable.
+ , runST -- :: (forall s. ST s a) -> a
+ , fixST -- :: (a -> ST s a) -> ST s a
+ , unsafeInterleaveST -- :: ST s a -> ST s a
+
+ , unsafeIOToST -- :: IO a -> ST s a
+
+ , RealWorld -- abstract
+ , stToIO -- :: ST RealWorld a -> IO a
+ ) where
+
+import Prelude
+
+import Data.Dynamic
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.ST
+import GHC.Prim ( unsafeCoerce#, RealWorld )
+import GHC.IOBase ( IO(..), stToIO )
+
+unsafeIOToST :: IO a -> ST s a
+unsafeIOToST (IO io) = ST $ \ s ->
+ case ((unsafeCoerce# io) s) of
+ (# new_s, a #) -> unsafeCoerce# (STret new_s a)
+#endif
+
+-- ---------------------------------------------------------------------------
+-- Typeable instance
+
+sTTc :: TyCon
+sTTc = mkTyCon "ST"
+
+instance (Typeable a, Typeable b) => Typeable (ST a b) where
+ typeOf st = mkAppTy sTTc [typeOf ((undefined :: ST a b -> a) st),
+ typeOf ((undefined :: ST a b -> b) st)]
diff --git a/libraries/base/Control/Monad/ST/Lazy.hs b/libraries/base/Control/Monad/ST/Lazy.hs
new file mode 100644
index 0000000000..24b396d686
--- /dev/null
+++ b/libraries/base/Control/Monad/ST/Lazy.hs
@@ -0,0 +1,247 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.ST.Lazy
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Lazy.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- This module presents an identical interface to Control.Monad.ST,
+-- but the underlying implementation of the state thread is lazy.
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.ST.Lazy (
+ ST,
+
+ runST,
+ unsafeInterleaveST,
+ fixST,
+
+ STRef.STRef,
+ newSTRef, readSTRef, writeSTRef,
+
+ STArray.STArray,
+ newSTArray, readSTArray, writeSTArray, boundsSTArray,
+ thawSTArray, freezeSTArray, unsafeFreezeSTArray,
+#ifdef __GLASGOW_HASKELL__
+-- no 'good' reason, just doesn't support it right now.
+ unsafeThawSTArray,
+#endif
+
+ ST.unsafeIOToST, ST.stToIO,
+
+ strictToLazyST, lazyToStrictST
+ ) where
+
+import Prelude
+
+import qualified Data.STRef as STRef
+import Data.Array
+
+#ifdef __GLASGOW_HASKELL__
+import qualified Control.Monad.ST as ST
+import qualified GHC.Arr as STArray
+import qualified GHC.ST
+import GHC.Base ( ($), ()(..) )
+import Control.Monad
+import Data.Ix
+import GHC.Prim
+#endif
+
+#ifdef __HUGS__
+import qualified ST
+import Monad
+import Ix
+import Array
+import PrelPrim ( unST
+ , mkST
+ , PrimMutableArray
+ , PrimArray
+ , primNewArray
+ , primReadArray
+ , primWriteArray
+ , primUnsafeFreezeArray
+ , primSizeMutableArray
+ , primSizeArray
+ , primIndexArray
+ )
+#endif
+
+
+#ifdef __GLASGOW_HASKELL__
+newtype ST s a = ST (State s -> (a, State s))
+data State s = S# (State# s)
+#endif
+
+#ifdef __HUGS__
+newtype ST s a = ST (s -> (a,s))
+#endif
+
+instance Functor (ST s) where
+ fmap f m = ST $ \ s ->
+ let
+ ST m_a = m
+ (r,new_s) = m_a s
+ in
+ (f r,new_s)
+
+instance Monad (ST s) where
+
+ return a = ST $ \ s -> (a,s)
+ m >> k = m >>= \ _ -> k
+ fail s = error s
+
+ (ST m) >>= k
+ = ST $ \ s ->
+ let
+ (r,new_s) = m s
+ ST k_a = k r
+ in
+ k_a new_s
+
+
+#ifdef __GLASGOW_HASKELL__
+{-# NOINLINE runST #-}
+runST :: (forall s. ST s a) -> a
+runST st = case st of ST the_st -> let (r,_) = the_st (S# realWorld#) in r
+#endif
+
+#ifdef __HUGS__
+runST :: (__forall s. ST s a) -> a
+runST st = case st of ST the_st -> let (r,_) = the_st realWorld in r
+ where realWorld = error "runST: entered the RealWorld"
+#endif
+
+fixST :: (a -> ST s a) -> ST s a
+fixST m = ST (\ s ->
+ let
+ ST m_r = m r
+ (r,s) = m_r s
+ in
+ (r,s))
+
+-- ---------------------------------------------------------------------------
+-- Variables
+
+newSTRef :: a -> ST s (STRef.STRef s a)
+readSTRef :: STRef.STRef s a -> ST s a
+writeSTRef :: STRef.STRef s a -> a -> ST s ()
+
+newSTRef = strictToLazyST . STRef.newSTRef
+readSTRef = strictToLazyST . STRef.readSTRef
+writeSTRef r a = strictToLazyST (STRef.writeSTRef r a)
+
+-- --------------------------------------------------------------------------
+-- Arrays
+
+newSTArray :: Ix ix => (ix,ix) -> elt -> ST s (STArray.STArray s ix elt)
+readSTArray :: Ix ix => STArray.STArray s ix elt -> ix -> ST s elt
+writeSTArray :: Ix ix => STArray.STArray s ix elt -> ix -> elt -> ST s ()
+boundsSTArray :: Ix ix => STArray.STArray s ix elt -> (ix, ix)
+thawSTArray :: Ix ix => Array ix elt -> ST s (STArray.STArray s ix elt)
+freezeSTArray :: Ix ix => STArray.STArray s ix elt -> ST s (Array ix elt)
+unsafeFreezeSTArray :: Ix ix => STArray.STArray s ix elt -> ST s (Array ix elt)
+
+#ifdef __GLASGOW_HASKELL__
+
+newSTArray ixs init = strictToLazyST (STArray.newSTArray ixs init)
+
+readSTArray arr ix = strictToLazyST (STArray.readSTArray arr ix)
+writeSTArray arr ix v = strictToLazyST (STArray.writeSTArray arr ix v)
+boundsSTArray arr = STArray.boundsSTArray arr
+thawSTArray arr = strictToLazyST (STArray.thawSTArray arr)
+freezeSTArray arr = strictToLazyST (STArray.freezeSTArray arr)
+unsafeFreezeSTArray arr = strictToLazyST (STArray.unsafeFreezeSTArray arr)
+unsafeThawSTArray arr = strictToLazyST (STArray.unsafeThawSTArray arr)
+#endif
+
+
+#ifdef __HUGS__
+newSTArray ixs elt = do
+ { arr <- strictToLazyST (primNewArray (rangeSize ixs) elt)
+ ; return (STArray ixs arr)
+ }
+
+boundsSTArray (STArray ixs arr) = ixs
+readSTArray (STArray ixs arr) ix
+ = strictToLazyST (primReadArray arr (index ixs ix))
+writeSTArray (STArray ixs arr) ix elt
+ = strictToLazyST (primWriteArray arr (index ixs ix) elt)
+freezeSTArray (STArray ixs arr) = do
+ { arr' <- strictToLazyST (primFreezeArray arr)
+ ; return (Array ixs arr')
+ }
+
+unsafeFreezeSTArray (STArray ixs arr) = do
+ { arr' <- strictToLazyST (primUnsafeFreezeArray arr)
+ ; return (Array ixs arr')
+ }
+
+thawSTArray (Array ixs arr) = do
+ { arr' <- strictToLazyST (primThawArray arr)
+ ; return (STArray ixs arr')
+ }
+
+primFreezeArray :: PrimMutableArray s a -> ST.ST s (PrimArray a)
+primFreezeArray arr = do
+ { let n = primSizeMutableArray arr
+ ; arr' <- primNewArray n arrEleBottom
+ ; mapM_ (copy arr arr') [0..n-1]
+ ; primUnsafeFreezeArray arr'
+ }
+ where
+ copy arr arr' i = do { x <- primReadArray arr i; primWriteArray arr' i x }
+ arrEleBottom = error "primFreezeArray: panic"
+
+primThawArray :: PrimArray a -> ST.ST s (PrimMutableArray s a)
+primThawArray arr = do
+ { let n = primSizeArray arr
+ ; arr' <- primNewArray n arrEleBottom
+ ; mapM_ (copy arr arr') [0..n-1]
+ ; return arr'
+ }
+ where
+ copy arr arr' i = primWriteArray arr' i (primIndexArray arr i)
+ arrEleBottom = error "primFreezeArray: panic"
+#endif
+
+-- ---------------------------------------------------------------------------
+-- Strict <--> Lazy
+
+#ifdef __GLASGOW_HASKELL__
+strictToLazyST :: ST.ST s a -> ST s a
+strictToLazyST m = ST $ \s ->
+ let
+ pr = case s of { S# s# -> GHC.ST.liftST m s# }
+ r = case pr of { GHC.ST.STret _ v -> v }
+ s' = case pr of { GHC.ST.STret s2# _ -> S# s2# }
+ in
+ (r, s')
+
+lazyToStrictST :: ST s a -> ST.ST s a
+lazyToStrictST (ST m) = GHC.ST.ST $ \s ->
+ case (m (S# s)) of (a, S# s') -> (# s', a #)
+#endif
+
+#ifdef __HUGS__
+strictToLazyST :: ST.ST s a -> ST s a
+strictToLazyST m = ST $ \s ->
+ let
+ pr = unST m s
+ r = fst pr
+ s' = snd pr
+ in
+ (r, s')
+
+
+lazyToStrictST :: ST s a -> ST.ST s a
+lazyToStrictST (ST m) = mkST $ m
+#endif
+
+unsafeInterleaveST :: ST s a -> ST s a
+unsafeInterleaveST = strictToLazyST . ST.unsafeInterleaveST . lazyToStrictST
diff --git a/libraries/base/Control/Monad/ST/Strict.hs b/libraries/base/Control/Monad/ST/Strict.hs
new file mode 100644
index 0000000000..927c462b48
--- /dev/null
+++ b/libraries/base/Control/Monad/ST/Strict.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.ST.Strict
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Strict.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The strict ST monad (identical to Control.Monad.ST)
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.ST.Strict (
+ module Control.Monad.ST
+ ) where
+
+import Prelude
+import Control.Monad.ST
diff --git a/libraries/base/Control/Monad/State.hs b/libraries/base/Control/Monad/State.hs
new file mode 100644
index 0000000000..b28d027c4c
--- /dev/null
+++ b/libraries/base/Control/Monad/State.hs
@@ -0,0 +1,227 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.State
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable ( requires mulit-parameter type classes,
+-- requires functional dependencies )
+--
+-- $Id: State.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- State monads.
+--
+-- Inspired by the paper
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+-----------------------------------------------------------------------------
+
+module Control.Monad.State (
+ MonadState(..),
+ modify,
+ gets,
+ State(..),
+ runState,
+ evalState,
+ execState,
+ mapState,
+ withState,
+ StateT(..),
+ runStateT,
+ evalStateT,
+ execStateT,
+ mapStateT,
+ withStateT,
+ module Control.Monad,
+ module Control.Monad.Fix,
+ module Control.Monad.Trans,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Fix
+import Control.Monad.Trans
+import Control.Monad.Reader
+import Control.Monad.Writer
+
+-- ---------------------------------------------------------------------------
+-- MonadState class
+--
+-- get: returns the state from the internals of the monad.
+-- put: changes (replaces) the state inside the monad.
+
+class (Monad m) => MonadState s m | m -> s where
+ get :: m s
+ put :: s -> m ()
+
+-- Monadic state transformer.
+--
+-- Maps an old state to a new state inside a state monad.
+-- The old state is thrown away.}
+--
+-- Main> :t modify ((+1) :: Int -> Int)
+-- modify (...) :: (MonadState Int a) => a ()
+--
+-- This says that modify (+1) acts over any
+-- Monad that is a member of the MonadState class,
+-- with an Int state.
+
+modify :: (MonadState s m) => (s -> s) -> m ()
+modify f = do
+ s <- get
+ put (f s)
+
+-- Get part of the state
+--
+-- gets specific component of the state,
+-- using a projection function supplied.
+
+gets :: (MonadState s m) => (s -> a) -> m a
+gets f = do
+ s <- get
+ return (f s)
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable state monad
+
+newtype State s a = State { runState :: s -> (a, s) }
+
+-- The State Monad structure is paramterized over just the state.
+
+instance Functor (State s) where
+ fmap f m = State $ \s -> let
+ (a, s') = runState m s
+ in (f a, s')
+
+instance Monad (State s) where
+ return a = State $ \s -> (a, s)
+ m >>= k = State $ \s -> let
+ (a, s') = runState m s
+ in runState (k a) s'
+
+instance MonadFix (State s) where
+ mfix f = State $ \s -> let (a, s') = runState (f a) s in (a, s')
+
+instance MonadState s (State s) where
+ get = State $ \s -> (s, s)
+ put s = State $ \_ -> ((), s)
+
+
+evalState :: State s a -> s -> a
+evalState m s = fst (runState m s)
+
+execState :: State s a -> s -> s
+execState m s = snd (runState m s)
+
+mapState :: ((a, s) -> (b, s)) -> State s a -> State s b
+mapState f m = State $ f . runState m
+
+withState :: (s -> s) -> State s a -> State s a
+withState f m = State $ runState m . f
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable state monad, with an inner monad
+
+newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
+
+--The StateT Monad structure is parameterized over two things:
+--
+-- * s - The state.
+-- * m - The inner monad.
+
+-- Here are some examples of use:
+
+-- (Parser from ParseLib with Hugs)
+-- type Parser a = StateT String [] a
+-- ==> StateT (String -> [(a,String)])
+-- For example, item can be written as:
+-- item = do (x:xs) <- get
+-- put xs
+-- return x
+
+-- type BoringState s a = StateT s Indentity a
+-- ==> StateT (s -> Identity (a,s))
+--
+-- type StateWithIO s a = StateT s IO a
+-- ==> StateT (s -> IO (a,s))
+--
+-- type StateWithErr s a = StateT s Maybe a
+-- ==> StateT (s -> Maybe (a,s))
+
+instance (Monad m) => Functor (StateT s m) where
+ fmap f m = StateT $ \s -> do
+ (x, s') <- runStateT m s
+ return (f x, s')
+
+instance (Monad m) => Monad (StateT s m) where
+ return a = StateT $ \s -> return (a, s)
+ m >>= k = StateT $ \s -> do
+ (a, s') <- runStateT m s
+ runStateT (k a) s'
+ fail str = StateT $ \_ -> fail str
+
+instance (MonadPlus m) => MonadPlus (StateT s m) where
+ mzero = StateT $ \_ -> mzero
+ m `mplus` n = StateT $ \s -> runStateT m s `mplus` runStateT n s
+
+instance (MonadFix m) => MonadFix (StateT s m) where
+ mfix f = StateT $ \s -> mfix $ \ ~(a, _) -> runStateT (f a) s
+
+instance (Monad m) => MonadState s (StateT s m) where
+ get = StateT $ \s -> return (s, s)
+ put s = StateT $ \_ -> return ((), s)
+
+instance MonadTrans (StateT s) where
+ lift m = StateT $ \s -> do
+ a <- m
+ return (a, s)
+
+instance (MonadIO m) => MonadIO (StateT s m) where
+ liftIO = lift . liftIO
+
+instance (MonadReader r m) => MonadReader r (StateT s m) where
+ ask = lift ask
+ local f m = StateT $ \s -> local f (runStateT m s)
+
+instance (MonadWriter w m) => MonadWriter w (StateT s m) where
+ tell = lift . tell
+ listen m = StateT $ \s -> do
+ ((a, s'), w) <- listen (runStateT m s)
+ return ((a, w), s')
+ pass m = StateT $ \s -> pass $ do
+ ((a, f), s') <- runStateT m s
+ return ((a, s'), f)
+
+
+evalStateT :: (Monad m) => StateT s m a -> s -> m a
+evalStateT m s = do
+ (a, _) <- runStateT m s
+ return a
+
+execStateT :: (Monad m) => StateT s m a -> s -> m s
+execStateT m s = do
+ (_, s') <- runStateT m s
+ return s'
+
+mapStateT :: (m (a, s) -> n (b, s)) -> StateT s m a -> StateT s n b
+mapStateT f m = StateT $ f . runStateT m
+
+withStateT :: (s -> s) -> StateT s m a -> StateT s m a
+withStateT f m = StateT $ runStateT m . f
+
+-- ---------------------------------------------------------------------------
+-- MonadState instances for other monad transformers
+
+instance (MonadState s m) => MonadState s (ReaderT r m) where
+ get = lift get
+ put = lift . put
+
+instance (Monoid w, MonadState s m) => MonadState s (WriterT w m) where
+ get = lift get
+ put = lift . put
diff --git a/libraries/base/Control/Monad/Trans.hs b/libraries/base/Control/Monad/Trans.hs
new file mode 100644
index 0000000000..376602107f
--- /dev/null
+++ b/libraries/base/Control/Monad/Trans.hs
@@ -0,0 +1,46 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Trans
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : portable
+--
+-- $Id: Trans.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The MonadTrans class.
+--
+-- Inspired by the paper
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+-----------------------------------------------------------------------------
+
+module Control.Monad.Trans (
+ MonadTrans(..),
+ MonadIO(..),
+ ) where
+
+import Prelude
+
+import System.IO
+
+-- ---------------------------------------------------------------------------
+-- MonadTrans class
+--
+-- Monad to facilitate stackable Monads.
+-- Provides a way of digging into an outer
+-- monad, giving access to (lifting) the inner monad.
+
+class MonadTrans t where
+ lift :: Monad m => m a -> t m a
+
+class (Monad m) => MonadIO m where
+ liftIO :: IO a -> m a
+
+instance MonadIO IO where
+ liftIO = id
diff --git a/libraries/base/Control/Monad/Writer.hs b/libraries/base/Control/Monad/Writer.hs
new file mode 100644
index 0000000000..96df1307be
--- /dev/null
+++ b/libraries/base/Control/Monad/Writer.hs
@@ -0,0 +1,170 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Monad.Writer
+-- Copyright : (c) Andy Gill 2001,
+-- (c) Oregon Graduate Institute of Science and Technology, 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable ( requires mulit-parameter type classes,
+-- requires functional dependencies )
+--
+-- $Id: Writer.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The MonadWriter class.
+--
+-- Inspired by the paper
+-- \em{Functional Programming with Overloading and
+-- Higher-Order Polymorphism},
+-- \A[HREF="http://www.cse.ogi.edu/~mpj"]{Mark P Jones},
+-- Advanced School of Functional Programming, 1995.}
+-----------------------------------------------------------------------------
+
+module Control.Monad.Writer (
+ MonadWriter(..),
+ listens,
+ censor,
+ Writer(..),
+ runWriter,
+ execWriter,
+ mapWriter,
+ WriterT(..),
+ runWriterT,
+ execWriterT,
+ mapWriterT,
+ module Control.Monad,
+ module Control.Monad.Monoid,
+ module Control.Monad.Fix,
+ module Control.Monad.Trans,
+ ) where
+
+import Prelude
+
+import Control.Monad
+import Control.Monad.Monoid
+import Control.Monad.Fix
+import Control.Monad.Trans
+import Control.Monad.Reader
+
+-- ---------------------------------------------------------------------------
+-- MonadWriter class
+--
+-- tell is like tell on the MUD's it shouts to monad
+-- what you want to be heard. The monad carries this 'packet'
+-- upwards, merging it if needed (hence the Monoid requirement)}
+--
+-- listen listens to a monad acting, and returns what the monad "said".
+--
+-- pass lets you provide a writer transformer which changes internals of
+-- the written object.
+
+class (Monoid w, Monad m) => MonadWriter w m | m -> w where
+ tell :: w -> m ()
+ listen :: m a -> m (a, w)
+ pass :: m (a, w -> w) -> m a
+
+listens :: (MonadWriter w m) => (w -> w) -> m a -> m (a, w)
+listens f m = do
+ (a, w) <- listen m
+ return (a, f w)
+
+censor :: (MonadWriter w m) => (w -> w) -> m a -> m a
+censor f m = pass $ do
+ a <- m
+ return (a, f)
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable writer monad
+
+newtype Writer w a = Writer { runWriter :: (a, w) }
+
+
+instance Functor (Writer w) where
+ fmap f m = Writer $ let (a, w) = runWriter m in (f a, w)
+
+instance (Monoid w) => Monad (Writer w) where
+ return a = Writer (a, mempty)
+ m >>= k = Writer $ let
+ (a, w) = runWriter m
+ (b, w') = runWriter (k a)
+ in (b, w `mappend` w')
+
+instance (Monoid w) => MonadFix (Writer w) where
+ mfix m = Writer $ let (a, w) = runWriter (m a) in (a, w)
+
+instance (Monoid w) => MonadWriter w (Writer w) where
+ tell w = Writer ((), w)
+ listen m = Writer $ let (a, w) = runWriter m in ((a, w), w)
+ pass m = Writer $ let ((a, f), w) = runWriter m in (a, f w)
+
+
+execWriter :: Writer w a -> w
+execWriter m = snd (runWriter m)
+
+mapWriter :: ((a, w) -> (b, w')) -> Writer w a -> Writer w' b
+mapWriter f m = Writer $ f (runWriter m)
+
+-- ---------------------------------------------------------------------------
+-- Our parameterizable writer monad, with an inner monad
+
+newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }
+
+
+instance (Monad m) => Functor (WriterT w m) where
+ fmap f m = WriterT $ do
+ (a, w) <- runWriterT m
+ return (f a, w)
+
+instance (Monoid w, Monad m) => Monad (WriterT w m) where
+ return a = WriterT $ return (a, mempty)
+ m >>= k = WriterT $ do
+ (a, w) <- runWriterT m
+ (b, w') <- runWriterT (k a)
+ return (b, w `mappend` w')
+ fail msg = WriterT $ fail msg
+
+instance (Monoid w, MonadPlus m) => MonadPlus (WriterT w m) where
+ mzero = WriterT mzero
+ m `mplus` n = WriterT $ runWriterT m `mplus` runWriterT n
+
+instance (Monoid w, MonadFix m) => MonadFix (WriterT w m) where
+ mfix m = WriterT $ mfix $ \ ~(a, _) -> runWriterT (m a)
+
+instance (Monoid w, Monad m) => MonadWriter w (WriterT w m) where
+ tell w = WriterT $ return ((), w)
+ listen m = WriterT $ do
+ (a, w) <- runWriterT m
+ return ((a, w), w)
+ pass m = WriterT $ do
+ ((a, f), w) <- runWriterT m
+ return (a, f w)
+
+instance (Monoid w) => MonadTrans (WriterT w) where
+ lift m = WriterT $ do
+ a <- m
+ return (a, mempty)
+
+instance (Monoid w, MonadIO m) => MonadIO (WriterT w m) where
+ liftIO = lift . liftIO
+
+instance (Monoid w, MonadReader r m) => MonadReader r (WriterT w m) where
+ ask = lift ask
+ local f m = WriterT $ local f (runWriterT m)
+
+
+execWriterT :: Monad m => WriterT w m a -> m w
+execWriterT m = do
+ (_, w) <- runWriterT m
+ return w
+
+mapWriterT :: (m (a, w) -> n (b, w')) -> WriterT w m a -> WriterT w' n b
+mapWriterT f m = WriterT $ f (runWriterT m)
+
+-- ---------------------------------------------------------------------------
+-- MonadWriter instances for other monad transformers
+
+instance (MonadWriter w m) => MonadWriter w (ReaderT r m) where
+ tell = lift . tell
+ listen m = ReaderT $ \w -> listen (runReaderT m w)
+ pass m = ReaderT $ \w -> pass (runReaderT m w)
diff --git a/libraries/base/Control/Parallel.hs b/libraries/base/Control/Parallel.hs
new file mode 100644
index 0000000000..1d6a126f1e
--- /dev/null
+++ b/libraries/base/Control/Parallel.hs
@@ -0,0 +1,62 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Parallel
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Parallel.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-- Parallel Constructs
+--
+-----------------------------------------------------------------------------
+
+module Control.Parallel (
+ par, seq -- re-exported
+#if defined(__GRANSIM__)
+ , parGlobal, parLocal, parAt, parAtAbs, parAtRel, parAtForNow
+#endif
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Conc ( par )
+#endif
+
+#if defined(__GRANSIM__)
+import PrelBase
+import PrelErr ( parError )
+import PrelGHC ( parGlobal#, parLocal#, parAt#, parAtAbs#, parAtRel#, parAtForNow# )
+
+{-# INLINE parGlobal #-}
+{-# INLINE parLocal #-}
+{-# INLINE parAt #-}
+{-# INLINE parAtAbs #-}
+{-# INLINE parAtRel #-}
+{-# INLINE parAtForNow #-}
+parGlobal :: Int -> Int -> Int -> Int -> a -> b -> b
+parLocal :: Int -> Int -> Int -> Int -> a -> b -> b
+parAt :: Int -> Int -> Int -> Int -> a -> b -> c -> c
+parAtAbs :: Int -> Int -> Int -> Int -> Int -> a -> b -> b
+parAtRel :: Int -> Int -> Int -> Int -> Int -> a -> b -> b
+parAtForNow :: Int -> Int -> Int -> Int -> a -> b -> c -> c
+
+parGlobal (I# w) (I# g) (I# s) (I# p) x y = case (parGlobal# x w g s p y) of { 0# -> parError; _ -> y }
+parLocal (I# w) (I# g) (I# s) (I# p) x y = case (parLocal# x w g s p y) of { 0# -> parError; _ -> y }
+
+parAt (I# w) (I# g) (I# s) (I# p) v x y = case (parAt# x v w g s p y) of { 0# -> parError; _ -> y }
+parAtAbs (I# w) (I# g) (I# s) (I# p) (I# q) x y = case (parAtAbs# x q w g s p y) of { 0# -> parError; _ -> y }
+parAtRel (I# w) (I# g) (I# s) (I# p) (I# q) x y = case (parAtRel# x q w g s p y) of { 0# -> parError; _ -> y }
+parAtForNow (I# w) (I# g) (I# s) (I# p) v x y = case (parAtForNow# x v w g s p y) of { 0# -> parError; _ -> y }
+
+#endif
+
+-- Maybe parIO and the like could be added here later.
+#ifndef __GLASGOW_HASKELL__
+-- For now, Hugs does not support par properly.
+par a b = b
+#endif
diff --git a/libraries/base/Control/Parallel/Strategies.hs b/libraries/base/Control/Parallel/Strategies.hs
new file mode 100644
index 0000000000..cad9aa3bf1
--- /dev/null
+++ b/libraries/base/Control/Parallel/Strategies.hs
@@ -0,0 +1,964 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Control.Parallel.Strategies
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Strategies.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Parallel strategy combinators
+--
+-----------------------------------------------------------------------------
+
+{-
+Time-stamp: <Wed Mar 21 2001 00:45:34 Stardate: [-30]6360.15 hwloidl>
+$Id: Strategies.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+
+This module defines parallel strategy combinators
+
+ Phil Trinder, Hans-Wolfgang Loidl, Kevin Hammond et al.
+
+ Based on Version VII (1/5/96) `Strategies96' of type a -> ()
+
+Author: $Author: simonmar $
+Date: $Date: 2001/06/28 14:15:02 $
+Revision: $Revision: 1.1 $
+Source: $Source: /srv/cvs/cvs.haskell.org/fptools/libraries/base/Control/Parallel/Strategies.hs,v $
+State: $State: Exp $
+
+This module defines evaluation strategies for controlling the parallel
+evaluation of non-strict programs. They provide a clean separation between
+algorithmic and behavioural code.
+
+The functions described here, and their use is documented in
+
+"Algorithm + Strategy = Parallelism",
+P.W. Trinder, K. Hammond, H-W. Loidl, S.L. Peyton Jones
+In Journal of Functional Programming 8(1):23--60, January 1998.
+URL: http://www.cee.hw.ac.uk/~dsg/gph/papers/ps/strategies.ps.gz
+
+This module supports Haskell 1.2, Haskell 1.4 and Haskell98.
+The distinction is made based on the __HASKELL1__ CPP variable.
+Parts of the module could be rewritten using constructor classes.
+
+-----------------------------------------------------------------------------
+The history of the Strategies module:
+
+Changelog:
+$Log: Strategies.hs,v $
+Revision 1.1 2001/06/28 14:15:02 simonmar
+First cut of the Haskell Core Libraries
+=======================================
+
+NOTE: it's not meant to be a working snapshot. The code is just here
+to look at and so the NHC/Hugs guys can start playing around with it.
+
+There is no build system. For GHC, the libraries tree is intended to
+be grafted onto an existing fptools/ tree, and the Makefile in
+libraries/core is a quick hack for that setup. This won't work at the
+moment without the other changes needed in fptools/ghc, which I
+haven't committed because they'll cause breakage. However, with the
+changes required these sources build a working Prelude and libraries.
+
+The layout mostly follows the one we agreed on, with one or two minor
+changes; in particular the Data/Array layout probably isn't final
+(there are several choices here).
+
+The document is in libraries/core/doc as promised.
+
+The cbits stuff is just a copy of ghc/lib/std/cbits and has
+GHC-specific stuff in it. We should really separate the
+compiler-specific C support from any compiler-independent C support
+there might be.
+
+Don't pay too much attention to the portability or stability status
+indicated in the header of each source file at the moment - I haven't
+gone through to make sure they're all consistent and make sense.
+
+I'm using non-literate source outside of GHC/. Hope that's ok with
+everyone.
+
+We need to discuss how the build system is going to work...
+
+Revision 1.3 2001/03/22 03:51:12 hwloidl
+ -*- outline -*-
+Time-stamp: <Thu Mar 22 2001 03:50:16 Stardate: [-30]6365.79 hwloidl>
+
+This commit covers changes in GHC to get GUM (way=mp) and GUM/GdH (way=md)
+working. It is a merge of my working version of GUM, based on GHC 4.06,
+with GHC 4.11. Almost all changes are in the RTS (see below).
+
+GUM is reasonably stable, we used the 4.06 version in large-ish programs for
+recent papers. Couple of things I want to change, but nothing urgent.
+GUM/GdH has just been merged and needs more testing. Hope to do that in the
+next weeks. It works in our working build but needs tweaking to run.
+GranSim doesn't work yet (*sigh*). Most of the code should be in, but needs
+more debugging.
+
+ToDo: I still want to make the following minor modifications before the release
+- Better wrapper skript for parallel execution [ghc/compiler/main]
+- Update parallel docu: started on it but it's minimal [ghc/docs/users_guide]
+- Clean up [nofib/parallel]: it's a real mess right now (*sigh*)
+- Update visualisation tools (minor things only IIRC) [ghc/utils/parallel]
+- Add a Klingon-English glossary
+
+* RTS:
+
+Almost all changes are restricted to ghc/rts/parallel and should not
+interfere with the rest. I only comment on changes outside the parallel
+dir:
+
+- Several changes in Schedule.c (scheduling loop; createThreads etc);
+ should only affect parallel code
+- Added ghc/rts/hooks/ShutdownEachPEHook.c
+- ghc/rts/Linker.[ch]: GUM doesn't know about Stable Names (ifdefs)!!
+- StgMiscClosures.h: END_TSO_QUEUE etc now defined here (from StgMiscClosures.hc)
+ END_ECAF_LIST was missing a leading stg_
+- SchedAPI.h: taskStart now defined in here; it's only a wrapper around
+ scheduleThread now, but might use some init, shutdown later
+- RtsAPI.h: I have nuked the def of rts_evalNothing
+
+* Compiler:
+
+- ghc/compiler/main/DriverState.hs
+ added PVM-ish flags to the parallel way
+ added new ways for parallel ticky profiling and distributed exec
+
+- ghc/compiler/main/DriverPipeline.hs
+ added a fct run_phase_MoveBinary which is called with way=mp after linking;
+ it moves the bin file into a PVM dir and produces a wrapper script for
+ parallel execution
+ maybe cleaner to add a MoveBinary phase in DriverPhases.hs but this way
+ it's less intrusive and MoveBinary makes probably only sense for mp anyway
+
+* Nofib:
+
+- nofib/spectral/Makefile, nofib/real/Makefile, ghc/tests/programs/Makefile:
+ modified to skip some tests if HWL_NOFIB_HACK is set; only tmp to record
+ which test prgs cause problems in my working build right now
+
+Revision 1.2 2000/11/18 02:13:11 hwloidl
+Now provides explicit def of seq (rather than just re-exporting).
+Required by the current version of the compiler.
+
+Revision 1.1 2000/01/14 13:34:32 hwloidl
+Module for specifying (parallel) behavioural code.
+
+Revision 1.9 1997/10/01 00:27:19 hwloidl
+Type of par and seq changed to Done -> Done -> Done with Done = ()
+Works for Haskell 1.2 as well as Haskell 1.4 (checks the CPP variable
+__HASKELL1__ to distinguish setups).
+Fixed precedences for par and seq for Haskell 1.4 (stronger than using).
+New infix operators >| and >|| as aliases for par and seq as strategy
+combinators.
+
+Revision 1.8 1997/05/20 21:13:22 hwloidl
+Revised to use `demanding` and `sparking` (final JFP paper version)
+
+Revision 1.7 1997/04/02 21:26:21 hwloidl
+Minor changes in documentation, none in the code.
+
+
+revision 1.5
+Version VII.1; Strategies96; Type: a -> ()
+Minor changes to previous version.
+CPP flags now separate GUM from GranSim version.
+Infix declaration for `using` (important for e.g. quicksort where the old
+version puts parentheses in the wrong way).
+Moer instances for NFData and markStartegies (in GranSim setup only).
+
+revision 1.4
+Version VII; Strategies96; Type: a -> ()
+The type has changed again; with the old type it's not possible to describe
+all the strategies we want (for example seqPair r0 rnf which should not
+evaluate the first component of the pair at all). The () type acts as info
+that the strategy has been applied.
+The function `using` is used as inverse strategy application i.e.
+on top level we usually have something like res `using` strat where ...
+The markStrategy hack is included in this version: it attaches an Int value
+to the currently running strategy (this can be inherited by all sub-strats)
+It doesn't model the jumps between evaluating producer and consumer properly
+(for that something like cost centers would be necessary).
+
+revision 1.3
+Version VI (V-based); Strategies95; Type: a -> a
+Now uses library modules like FiniteMap with strategies in there.
+CPP flags for using the same module with GUM and GranSim.
+A few new strategies.
+
+revision 1.2
+Version V; Strategies95; Type: a -> a
+The type of Strategies has changed from a -> () to a -> a
+All strategies and instances of NFData have been redefined accordingly.
+This branch started off after discussions between PWT, SLPJ and HWL in
+mid Nov (start of development of the actual module: 10/1/96)
+
+revision 1.1 Initial revision
+-----------------------------------------------------------------------------
+-- To use fakeinfo first replace all %%$ by \@
+-- If you have fakeinfo makers in the file you need a slightly modified
+-- version of the lit-deatify script (called by lit2pgm). You get that
+-- version on Suns and Alphas in Glasgow by using
+-- \tr{lit2pgm -H "${HOME}/bin/`hw_os`"}
+-- in your Makefile
+-----------------------------------------------------------------------------
+
+--@node Evaluation Strategies, , ,
+--@chapter Evaluation Strategies
+
+--@menu
+--* Imports and infix declarations::
+--* Strategy Type and Application::
+--* Basic Strategies::
+--* Strategic Function Application::
+--* Marking a Strategy::
+--* Strategy Instances::
+--* Lolita-specific Strategies::
+--@end menu
+
+--@node Imports and infix declarations, Strategy Type and Application, Evaluation Strategies, Evaluation Strategies
+--@section Imports and infix declarations
+
+> module Strategies(
+>#if (__HASKELL1__>=4)
+> module Strategies,
+> module Parallel
+>#else
+> Strategies..
+>#endif
+> ) where
+>
+>#if defined(GRAN) && !(__HASKELL1__>=4)
+> import PreludeGlaST -- only needed for markStrat
+>#endif
+>#if (__HASKELL1__>=4)
+
+<> import Prelude hiding (seq)
+<> import qualified Parallel
+
+> import Parallel
+
+>#else
+> import Parallel renaming (par to par_from_Parallel, seq to seq_from_Parallel)
+>#endif
+
+>#if (__HASKELL1__>=4)
+> import Ix
+> import Array
+>#endif
+
+>#if defined(PAR_GRAN_LIST)
+> import QSort -- tmp (only for parGranList)
+>#endif
+
+I lifted the precedence of @par@ and @seq@ by one level to make @using@ the
+combinator with the weakest precedence.
+Oooops, there seems to be a bug in ghc 0.29 prohibiting another infix
+declaration of @par@ and @seq@ despite renaming the imported versions.
+
+>#if (__HASKELL1__>=4)
+
+<> infixr 2 `par` -- was: 0
+<> infixr 3 `seq` -- was: 1
+
+>#else
+> infixr 0 `par` -- was: 0
+> infixr 1 `seq` -- was: 1
+>#endif
+
+> infixl 0 `using`,`demanding`,`sparking` -- weakest precedence!
+
+> infixr 2 >|| -- another name for par
+> infixr 3 >| -- another name for seq
+> infixl 6 $||, $| -- strategic function application (seq and par)
+> infixl 9 .|, .||, -|, -|| -- strategic (inverse) function composition
+
+> strategy_version = "$Revision: 1.1 $"
+> strategy_id = "$Id: Strategies.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $"
+
+------------------------------------------------------------------------------
+ Strategy Type, Application and Semantics
+------------------------------------------------------------------------------
+--@node Strategy Type and Application, Basic Strategies, Imports and infix declarations, Evaluation Strategies
+--@section Strategy Type and Application
+
+--@cindex Strategy
+
+> type Done = ()
+> type Strategy a = a -> Done
+
+A strategy takes a value and returns a dummy `done' value to indicate that
+the specifed evaluation has been performed.
+
+The basic combinators for strategies are @par@ and @seq@ but with types that
+indicate that they only combine the results of a strategy application.
+
+NB: This version can be used with Haskell 1.4 (GHC 2.05 and beyond), *but*
+ you won't get strategy checking on seq (only on par)!
+
+The infix fcts >| and >|| are alternative names for `seq` and `par`.
+With the introduction of a Prelude function `seq` separating the Prelude
+function from the Strategy function becomes a pain. The notation also matches
+the notation for strategic function application.
+
+--@cindex par
+--@cindex seq
+--@cindex >|
+--@cindex >||
+
+>#if (__HASKELL1__>=4)
+
+par and seq have the same types as before; >| and >|| are more specific
+and can only be used when composing strategies.
+
+<> par :: Done -> Done -> Done
+<> par = Parallel.par
+<> seq :: a -> b -> b -- that's the real type of seq defined in Prelude
+<> seq = Parallel.seq
+
+> (>|), (>||) :: Done -> Done -> Done
+> {-# INLINE (>|) #-}
+> {-# INLINE (>||) #-}
+> (>|) = Prelude.seq
+> (>||) = Parallel.par
+>#else
+> par, seq, (>|), (>||) :: Done -> Done -> Done
+> par = par_from_Parallel
+> seq = seq_from_Parallel
+> {-# INLINE (>|) #-}
+> {-# INLINE (>||) #-}
+> (>|) = seq
+> (>||) = par
+>#endif
+
+--@cindex using
+
+> using :: a -> Strategy a -> a
+>#if (__HASKELL1__>=4)
+> using x s = s x `seq` x
+>#else
+> using x s = s x `seq_from_Parallel` x
+>#endif
+
+using takes a strategy and a value, and applies the strategy to the
+value before returning the value. Used to express data-oriented parallelism
+
+x `using` s is a projection on x, i.e. both
+
+ a retraction: x `using` s [ x
+ -
+ and idempotent: (x `using` s) `using` s = x `using` s
+
+demanding and sparking are used to express control-oriented
+parallelism. Their second argument is usually a sequence of strategy
+applications combined `par` and `seq`. Sparking should only be used
+with a singleton sequence as it is not necessarily excuted
+
+--@cindex demanding
+--@cindex sparking
+
+> demanding, sparking :: a -> Done -> a
+>#if (__HASKELL1__>=4)
+> demanding = flip Parallel.seq
+> sparking = flip Parallel.par
+>#else
+> demanding = flip seq_from_Parallel
+> sparking = flip par_from_Parallel
+>#endif
+
+sPar and sSeq have been superceded by sparking and demanding: replace
+ e `using` sPar x with e `sparking` x
+ e `using` sSeq x with e `demanding` x
+
+<sPar is a strategy corresponding to par. i.e. x `par` e <=> e `using` sPar x
+<
+<> sPar :: a -> Strategy b
+<> sPar x y = x `par` ()
+<
+<sSeq is a strategy corresponding to seq. i.e. x `seq` e <=> e `using` sSeq x
+<
+<> sSeq :: a -> Strategy b
+<> sSeq x y = x `seq` ()
+
+-----------------------------------------------------------------------------
+ Basic Strategies
+-----------------------------------------------------------------------------
+--@node Basic Strategies, Strategic Function Application, Strategy Type and Application, Evaluation Strategies
+--@section Basic Strategies
+
+r0 performs *no* evaluation on its argument.
+
+--@cindex r0
+
+> r0 :: Strategy a
+> r0 x = ()
+
+rwhnf reduces its argument to weak head normal form.
+
+--@cindex rwhnf
+--@cindex rnf
+--@cindex NFData
+
+>#if defined(__HASKELL98__)
+> rwhnf :: Strategy a
+> rwhnf x = x `seq` ()
+>#elif (__HASKELL1__==4)
+> rwhnf :: Eval a => Strategy a
+> rwhnf x = x `seq` ()
+>#else
+> rwhnf :: Strategy a
+> rwhnf x = x `seq_from_Parallel` ()
+>#endif
+
+>#if defined(__HASKELL98__)
+> class NFData a where
+>#elif (__HASKELL1__>=4)
+> class Eval a => NFData a where
+>#else
+> class NFData a where
+>#endif
+> -- rnf reduces its argument to (head) normal form
+> rnf :: Strategy a
+> -- Default method. Useful for base types. A specific method is necessay for
+> -- constructed types
+> rnf = rwhnf
+>
+> class (NFData a, Integral a) => NFDataIntegral a
+> class (NFData a, Ord a) => NFDataOrd a
+
+------------------------------------------------------------------------------
+ Strategic Function Application
+------------------------------------------------------------------------------
+--@node Strategic Function Application, Marking a Strategy, Basic Strategies, Evaluation Strategies
+--@section Strategic Function Application
+
+The two infix functions @$|@ and @$||@ perform sequential and parallel
+function application, respectively. They are parameterised with a strategy
+that is applied to the argument of the function application. This is very
+handy when writing pipeline parallelism as a sequence of @$@, @$|@ and
+@$||@'s. There is no need of naming intermediate values in this case. The
+separation of algorithm from strategy is achieved by allowing strategies
+only as second arguments to @$|@ and @$||@.
+
+--@cindex $|
+--@cindex $||
+
+> ($|), ($||) :: (a -> b) -> Strategy a -> a -> b
+
+<> f $| s = \ x -> f x `using` \ _ -> s x `seq` ()
+<> f $|| s = \ x -> f x `using` \ _ -> s x `par` ()
+
+> f $| s = \ x -> f x `demanding` s x
+> f $|| s = \ x -> f x `sparking` s x
+
+The same thing for function composition (.| and .||) and inverse function
+composition (-| and -||) for those who read their programs from left to
+right.
+
+--@cindex .|
+--@cindex .||
+--@cindex -|
+--@cindex -||
+
+> (.|), (.||) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
+> (-|), (-||) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
+
+> (.|) f s g = \ x -> let gx = g x
+> in f gx `demanding` s gx
+> (.||) f s g = \ x -> let gx = g x
+> in f gx `sparking` s gx
+
+> (-|) f s g = \ x -> let fx = f x
+> in g fx `demanding` s fx
+> (-||) f s g = \ x -> let fx = f x
+> in g fx `sparking` s fx
+
+------------------------------------------------------------------------------
+ Marking a Strategy
+------------------------------------------------------------------------------
+--@node Marking a Strategy, Strategy Instances, Strategic Function Application, Evaluation Strategies
+--@section Marking a Strategy
+
+Marking a strategy.
+
+Actually, @markStrat@ sticks a label @n@ into the sparkname field of the
+thread executing strategy @s@. Together with a runtime-system that supports
+propagation of sparknames to the children this means that this strategy and
+all its children have the sparkname @n@ (if the static sparkname field in
+the @parGlobal@ annotation contains the value 1). Note, that the @SN@ field
+of starting the marked strategy itself contains the sparkname of the parent
+thread. The END event contains @n@ as sparkname.
+
+--@cindex markStrat
+
+>#if defined(GRAN) && !(__HASKELL1__>=4)
+> markStrat :: Int -> Strategy a -> Strategy a
+> markStrat n s x = unsafePerformPrimIO (
+> _casm_ ``%r = set_sparkname(CurrentTSO, %0);'' n `thenPrimIO` \ z ->
+> returnPrimIO (s x))
+>#endif
+
+-----------------------------------------------------------------------------
+ Strategy Instances and Functions
+-----------------------------------------------------------------------------
+--@node Strategy Instances, Lolita-specific Strategies, Marking a Strategy, Evaluation Strategies
+--@section Strategy Instances
+-----------------------------------------------------------------------------
+ Tuples
+-----------------------------------------------------------------------------
+--@menu
+--* Tuples::
+--* Numbers::
+--* Characters::
+--* Booleans::
+--* Unit::
+--* Lists::
+--* Arrays::
+--@end menu
+
+--@node Tuples, Numbers, Strategy Instances, Strategy Instances
+--@subsection Tuples
+
+We currently support up to 9-tuples. If you need longer tuples you have to
+add the instance explicitly to your program.
+
+> instance (NFData a, NFData b) => NFData (a,b) where
+> rnf (x,y) = rnf x `seq` rnf y
+
+> instance (NFData a, NFData b, NFData c) => NFData (a,b,c) where
+> rnf (x,y,z) = rnf x `seq` rnf y `seq` rnf z
+
+> instance (NFData a, NFData b, NFData c, NFData d) => NFData (a,b,c,d) where
+> rnf (x1,x2,x3,x4) = rnf x1 `seq`
+> rnf x2 `seq`
+> rnf x3 `seq`
+> rnf x4
+
+> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
+> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) =>
+> NFData (a1, a2, a3, a4, a5) where
+> rnf (x1, x2, x3, x4, x5) =
+> rnf x1 `seq`
+> rnf x2 `seq`
+> rnf x3 `seq`
+> rnf x4 `seq`
+> rnf x5
+
+> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
+> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) =>
+> NFData (a1, a2, a3, a4, a5, a6) where
+> rnf (x1, x2, x3, x4, x5, x6) =
+> rnf x1 `seq`
+> rnf x2 `seq`
+> rnf x3 `seq`
+> rnf x4 `seq`
+> rnf x5 `seq`
+> rnf x6
+
+> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
+> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) =>
+> NFData (a1, a2, a3, a4, a5, a6, a7) where
+> rnf (x1, x2, x3, x4, x5, x6, x7) =
+> rnf x1 `seq`
+> rnf x2 `seq`
+> rnf x3 `seq`
+> rnf x4 `seq`
+> rnf x5 `seq`
+> rnf x6 `seq`
+> rnf x7
+
+> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
+> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) =>
+> NFData (a1, a2, a3, a4, a5, a6, a7, a8) where
+> rnf (x1, x2, x3, x4, x5, x6, x7, x8) =
+> rnf x1 `seq`
+> rnf x2 `seq`
+> rnf x3 `seq`
+> rnf x4 `seq`
+> rnf x5 `seq`
+> rnf x6 `seq`
+> rnf x7 `seq`
+> rnf x8
+
+> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
+> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8, NFData a9) =>
+> NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
+> rnf (x1, x2, x3, x4, x5, x6, x7, x8, x9) =
+> rnf x1 `seq`
+> rnf x2 `seq`
+> rnf x3 `seq`
+> rnf x4 `seq`
+> rnf x5 `seq`
+> rnf x6 `seq`
+> rnf x7 `seq`
+> rnf x8 `seq`
+> rnf x9
+
+--@cindex seqPair
+
+> seqPair :: Strategy a -> Strategy b -> Strategy (a,b)
+> seqPair strata stratb (x,y) = strata x `seq` stratb y
+
+--@cindex parPair
+
+> parPair :: Strategy a -> Strategy b -> Strategy (a,b)
+> parPair strata stratb (x,y) = strata x `par` stratb y `par` ()
+
+The reason for the second `par` is so that the strategy terminates
+quickly. This is important if the strategy is used as the 1st argument of a seq
+
+--@cindex seqTriple
+
+> seqTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
+> seqTriple strata stratb stratc p@(x,y,z) =
+> strata x `seq`
+> stratb y `seq`
+> stratc z
+
+--@cindex parTriple
+
+> parTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
+> parTriple strata stratb stratc (x,y,z) =
+> strata x `par`
+> stratb y `par`
+> stratc z `par`
+> ()
+
+-----------------------------------------------------------------------------
+ Numbers
+-----------------------------------------------------------------------------
+--@node Numbers, Characters, Tuples, Strategy Instances
+--@subsection Numbers
+
+Weak head normal form and normal form are identical for integers, so the
+default rnf is sufficient.
+
+> instance NFData Int
+> instance NFData Integer
+> instance NFData Float
+> instance NFData Double
+
+> instance NFDataIntegral Int
+> instance NFDataOrd Int
+
+Rational and complex numbers.
+
+>#if !(__HASKELL1__>=4)
+> instance (NFData a) => NFData (Ratio a) where
+> rnf (x:%y) = rnf x `seq`
+> rnf y `seq`
+> ()
+
+> instance (NFData a) => NFData (Complex a) where
+> rnf (x:+y) = rnf x `seq`
+> rnf y `seq`
+> ()
+>#endif
+
+-----------------------------------------------------------------------------
+ Characters
+-----------------------------------------------------------------------------
+--@node Characters, Booleans, Numbers, Strategy Instances
+--@subsection Characters
+
+> instance NFData Char
+
+-----------------------------------------------------------------------------
+ Bools
+-----------------------------------------------------------------------------
+--@node Booleans, Unit, Characters, Strategy Instances
+--@subsection Booleans
+
+> instance NFData Bool
+
+-----------------------------------------------------------------------------
+ Unit
+-----------------------------------------------------------------------------
+--@node Unit, Lists, Booleans, Strategy Instances
+--@subsection Unit
+
+> instance NFData ()
+
+-----------------------------------------------------------------------------
+ Lists
+----------------------------------------------------------------------------
+--@node Lists, Arrays, Unit, Strategy Instances
+--@subsection Lists
+
+> instance NFData a => NFData [a] where
+> rnf [] = ()
+> rnf (x:xs) = rnf x `seq` rnf xs
+
+--@menu
+--* Parallel Strategies for Lists::
+--* Sequential Strategies for Lists::
+--@end menu
+
+----------------------------------------------------------------------------
+ Lists: Parallel Strategies
+----------------------------------------------------------------------------
+--@node Parallel Strategies for Lists, Sequential Strategies for Lists, Lists, Lists
+--@subsubsection Parallel Strategies for Lists
+
+Applies a strategy to every element of a list in parallel
+
+--@cindex parList
+
+> parList :: Strategy a -> Strategy [a]
+> parList strat [] = ()
+> parList strat (x:xs) = strat x `par` (parList strat xs)
+
+Applies a strategy to the first n elements of a list in parallel
+
+--@cindex parListN
+
+> parListN :: (Integral b) => b -> Strategy a -> Strategy [a]
+> parListN n strat [] = ()
+> parListN 0 strat xs = ()
+> parListN n strat (x:xs) = strat x `par` (parListN (n-1) strat xs)
+
+Evaluates N elements of the spine of the argument list and applies
+`strat' to the Nth element (if there is one) in parallel with the
+result. e.g. parListNth 2 [e1, e2, e3] evaluates e2
+
+--@cindex parListNth
+
+> parListNth :: Int -> Strategy a -> Strategy [a]
+> parListNth n strat xs
+> | null rest = ()
+> | otherwise = strat (head rest) `par` ()
+> where
+> rest = drop n xs
+
+parListChunk sequentially applies a strategy to chunks
+(sub-sequences) of a list in parallel. Useful to increase grain size
+
+--@cindex parListChunk
+
+> parListChunk :: Int -> Strategy a -> Strategy [a]
+> parListChunk n strat [] = ()
+> parListChunk n strat xs = seqListN n strat xs `par`
+> parListChunk n strat (drop n xs)
+
+parMap applies a function to each element of the argument list in
+parallel. The result of the function is evaluated using `strat'
+
+--@cindex parMap
+
+> parMap :: Strategy b -> (a -> b) -> [a] -> [b]
+> parMap strat f xs = map f xs `using` parList strat
+
+parFlatMap uses parMap to apply a list-valued function to each
+element of the argument list in parallel. The result of the function
+is evaluated using `strat'
+
+--@cindex parFlatMap
+
+> parFlatMap :: Strategy [b] -> (a -> [b]) -> [a] -> [b]
+> parFlatMap strat f xs = concat (parMap strat f xs)
+
+parZipWith zips together two lists with a function z in parallel
+
+--@cindex parZipWith
+
+> parZipWith :: Strategy c -> (a -> b -> c) -> [a] -> [b] -> [c]
+> parZipWith strat z as bs =
+> zipWith z as bs `using` parList strat
+
+----------------------------------------------------------------------------
+ Lists: Sequential Strategies
+----------------------------------------------------------------------------
+--@node Sequential Strategies for Lists, , Parallel Strategies for Lists, Lists
+--@subsubsection Sequential Strategies for Lists
+
+Sequentially applies a strategy to each element of a list
+
+--@cindex seqList
+
+> seqList :: Strategy a -> Strategy [a]
+> seqList strat [] = ()
+> seqList strat (x:xs) = strat x `seq` (seqList strat xs)
+
+Sequentially applies a strategy to the first n elements of a list
+
+--@cindex seqListN
+
+> seqListN :: (Integral a) => a -> Strategy b -> Strategy [b]
+> seqListN n strat [] = ()
+> seqListN 0 strat xs = ()
+> seqListN n strat (x:xs) = strat x `seq` (seqListN (n-1) strat xs)
+
+seqListNth applies a strategy to the Nth element of it's argument
+(if there is one) before returning the result. e.g. seqListNth 2 [e1,
+e2, e3] evaluates e2
+
+--@cindex seqListNth
+
+>#if (__HASKELL1__>=4)
+> seqListNth :: Int -> Strategy b -> Strategy [b]
+>#else
+> seqListNth :: (Integral a) => a -> Strategy b -> Strategy [b]
+>#endif
+> seqListNth n strat xs
+> | null rest = ()
+> | otherwise = strat (head rest)
+> where
+> rest = drop n xs
+
+Parallel n-buffer function added for the revised version of the strategies
+paper. @parBuffer@ supersedes the older @fringeList@. It has the same
+semantics.
+
+--@cindex parBuffer
+
+> parBuffer :: Int -> Strategy a -> [a] -> [a]
+> parBuffer n s xs =
+> return xs (start n xs)
+> where
+> return (x:xs) (y:ys) = (x:return xs ys) `sparking` s y
+> return xs [] = xs
+>
+> start n [] = []
+> start 0 ys = ys
+> start n (y:ys) = start (n-1) ys `sparking` s y
+
+fringeList implements a `rolling buffer' of length n, i.e.applies a
+strategy to the nth element of list when the head is demanded. More
+precisely:
+
+ semantics: fringeList n s = id :: [b] -> [b]
+ dynamic behaviour: evalutates the nth element of the list when the
+ head is demanded.
+
+The idea is to provide a `rolling buffer' of length n.
+
+--@cindex fringeList
+
+<> fringeList :: (Integral a) => a -> Strategy b -> [b] -> [b]
+<> fringeList n strat [] = []
+<> fringeList n strat (r:rs) =
+<> seqListNth n strat rs `par`
+<> r:fringeList n strat rs
+
+------------------------------------------------------------------------------
+ Arrays
+------------------------------------------------------------------------------
+--@node Arrays, , Lists, Strategy Instances
+--@subsection Arrays
+
+> instance (Ix a, NFData a, NFData b) => NFData (Array a b) where
+> rnf x = rnf (bounds x) `seq` seqList rnf (elems x) `seq` ()
+
+Apply a strategy to all elements of an array in parallel. This can be done
+either in sequentially or in parallel (same as with lists, really).
+
+> seqArr :: (Ix b) => Strategy a -> Strategy (Array b a)
+> seqArr s arr = seqList s (elems arr)
+
+> parArr :: (Ix b) => Strategy a -> Strategy (Array b a)
+> parArr s arr = parList s (elems arr)
+
+Associations maybe useful even withou mentioning Arrays.
+
+See: .../lib/prelude/TyArrays.hs:
+data Assoc a b = a := b deriving ()
+
+>#if (__HASKELL1__<4)
+> instance (NFData a, NFData b) => NFData (Assoc a b) where
+> rnf (x := y) = rnf x `seq` rnf y `seq` ()
+>#endif
+
+------------------------------------------------------------------------------
+ Some strategies specific for Lolita
+------------------------------------------------------------------------------
+--@node Lolita-specific Strategies, Index, Strategy Instances, Evaluation Strategies
+--@section Lolita-specific Strategies
+
+The following is useful in mergePenGroups
+
+--@cindex fstPairFstList
+
+> fstPairFstList :: (NFData a) => Strategy [(a,b)]
+> fstPairFstList = seqListN 1 (seqPair rwhnf r0)
+
+Some HACKs for Lolita. AFAIK force is just another name for our rnf and
+sforce is a shortcut (definition here is identical to the one in Force.lhs)
+
+> force :: (NFData a) => a -> a
+> sforce :: (NFData a) => a -> b -> b
+
+Same as definition below
+
+<> force x = rnf x `seq` x
+
+> force = id $| rnf
+>#if (__HASKELL1__>=4)
+> sforce x y = force x `seq` y
+>#else
+> sforce x y = force x `seq_from_Parallel` y
+>#endif
+
+--@node Bowing-alg specific strategies
+--@section Bowing-alg specific strategies
+
+NB: this strategy currently needs the quicksort implementation from the hbc syslib
+
+>#if defined(PAR_GRAN_LIST)
+> parGranList :: Strategy a -> (a -> Int) -> [a] -> Strategy [a]
+> parGranList s gran_estim l_in = \ l_out ->
+> parListByIdx s l_out $
+> sortedIdx gran_list (sortLe ( \ (i,_) (j,_) -> i>j) gran_list)
+> where -- spark list elems of l in the order specified by (i:idxs)
+> parListByIdx s l [] = ()
+> parListByIdx s l (i:idxs) = parListByIdx s l idxs `sparking` s (l!!i)
+> -- get the index of y in the list
+> idx y [] = error "idx: x not in l"
+> idx y ((x,_):xs) | y==x = 0
+> | otherwise = (idx y xs)+1
+> -- the `schedule' for sparking: list of indices of sorted input list
+> sortedIdx l idxs = [ idx x l | (x,_) <- idxs ]
+> -- add granularity info to elems of the input list
+> gran_list = map (\ l -> (gran_estim l, l)) l_in
+>#endif
+
+--@node Index, , Lolita-specific Strategies, Evaluation Strategies
+--@section Index
+
+--@index
+--* $|:: @cindex\s-+$|
+--* $||:: @cindex\s-+$||
+--* -|:: @cindex\s-+-|
+--* -||:: @cindex\s-+-||
+--* .|:: @cindex\s-+.|
+--* .||:: @cindex\s-+.||
+--* NFData:: @cindex\s-+NFData
+--* Strategy:: @cindex\s-+Strategy
+--* demanding:: @cindex\s-+demanding
+--* fringeList:: @cindex\s-+fringeList
+--* fstPairFstList:: @cindex\s-+fstPairFstList
+--* markStrat:: @cindex\s-+markStrat
+--* parBuffer:: @cindex\s-+parBuffer
+--* parFlatMap:: @cindex\s-+parFlatMap
+--* parList:: @cindex\s-+parList
+--* parListChunk:: @cindex\s-+parListChunk
+--* parListN:: @cindex\s-+parListN
+--* parListNth:: @cindex\s-+parListNth
+--* parMap:: @cindex\s-+parMap
+--* parPair:: @cindex\s-+parPair
+--* parTriple:: @cindex\s-+parTriple
+--* parZipWith:: @cindex\s-+parZipWith
+--* r0:: @cindex\s-+r0
+--* rnf:: @cindex\s-+rnf
+--* rwhnf:: @cindex\s-+rwhnf
+--* seqList:: @cindex\s-+seqList
+--* seqListN:: @cindex\s-+seqListN
+--* seqListNth:: @cindex\s-+seqListNth
+--* seqPair:: @cindex\s-+seqPair
+--* seqTriple:: @cindex\s-+seqTriple
+--* sparking:: @cindex\s-+sparking
+--* using:: @cindex\s-+using
+--@end index
diff --git a/libraries/base/Data/Array.hs b/libraries/base/Data/Array.hs
new file mode 100644
index 0000000000..c13cc91387
--- /dev/null
+++ b/libraries/base/Data/Array.hs
@@ -0,0 +1,145 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Array
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Array.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Basic non-strict arrays.
+--
+-----------------------------------------------------------------------------
+
+module Data.Array
+
+ (
+ module Data.Ix -- export all of Ix
+ , Array -- Array type is abstract
+
+ , array -- :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
+ , listArray -- :: (Ix a) => (a,a) -> [b] -> Array a b
+ , (!) -- :: (Ix a) => Array a b -> a -> b
+ , bounds -- :: (Ix a) => Array a b -> (a,a)
+ , indices -- :: (Ix a) => Array a b -> [a]
+ , elems -- :: (Ix a) => Array a b -> [b]
+ , assocs -- :: (Ix a) => Array a b -> [(a,b)]
+ , accumArray -- :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)] -> Array a b
+ , (//) -- :: (Ix a) => Array a b -> [(a,b)] -> Array a b
+ , accum -- :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)] -> Array a b
+ , ixmap -- :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c -> Array a b
+
+ -- Array instances:
+ --
+ -- Ix a => Functor (Array a)
+ -- (Ix a, Eq b) => Eq (Array a b)
+ -- (Ix a, Ord b) => Ord (Array a b)
+ -- (Ix a, Show a, Show b) => Show (Array a b)
+ -- (Ix a, Read a, Read b) => Read (Array a b)
+ --
+
+ -- Implementation checked wrt. Haskell 98 lib report, 1/99.
+
+ ) where
+
+import Data.Dynamic
+
+#ifdef __GLASGOW_HASKELL__
+import Data.Ix
+import GHC.Arr -- Most of the hard work is done here
+import GHC.Err ( undefined )
+#endif
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE2(Array,arrayTc,"Array")
+
+#ifdef __HUGS__
+ ------------ HUGS (rest of file) --------------------
+import PrelPrim ( PrimArray
+ , runST
+ , primNewArray
+ , primWriteArray
+ , primReadArray
+ , primUnsafeFreezeArray
+ , primIndexArray
+ )
+import Ix
+import List( (\\) )
+
+infixl 9 !, //
+
+-- -----------------------------------------------------------------------------
+-- The Array type
+
+data Array ix elt = Array (ix,ix) (PrimArray elt)
+
+array :: Ix a => (a,a) -> [(a,b)] -> Array a b
+array ixs@(ix_start, ix_end) ivs = runST (do
+ { mut_arr <- primNewArray (rangeSize ixs) arrEleBottom
+ ; mapM_ (\ (i,v) -> primWriteArray mut_arr (index ixs i) v) ivs
+ ; arr <- primUnsafeFreezeArray mut_arr
+ ; return (Array ixs arr)
+ }
+ )
+ where
+ arrEleBottom = error "(Array.!): undefined array element"
+
+listArray :: Ix a => (a,a) -> [b] -> Array a b
+listArray b vs = array b (zipWith (\ a b -> (a,b)) (range b) vs)
+
+(!) :: Ix a => Array a b -> a -> b
+(Array bounds arr) ! i = primIndexArray arr (index bounds i)
+
+bounds :: Ix a => Array a b -> (a,a)
+bounds (Array b _) = b
+
+indices :: Ix a => Array a b -> [a]
+indices = range . bounds
+
+elems :: Ix a => Array a b -> [b]
+elems a = [a!i | i <- indices a]
+
+assocs :: Ix a => Array a b -> [(a,b)]
+assocs a = [(i, a!i) | i <- indices a]
+
+(//) :: Ix a => Array a b -> [(a,b)] -> Array a b
+(//) a us = array (bounds a)
+ ([(i,a!i) | i <- indices a \\ [i | (i,_) <- us]]
+ ++ us)
+
+accum :: Ix a => (b -> c -> b) -> Array a b -> [(a,c)] -> Array a b
+accum f = foldl (\a (i,v) -> a // [(i,f (a!i) v)])
+
+accumArray :: Ix a => (b -> c -> b) -> b -> (a,a) -> [(a,c)] -> Array a b
+accumArray f z b = accum f (array b [(i,z) | i <- range b])
+
+ixmap :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c -> Array a c
+ixmap b f a = array b [(i, a ! f i) | i <- range b]
+
+
+instance (Ix a) => Functor (Array a) where
+ fmap f a = array (bounds a) [(i, f(a!i)) | i <- indices a]
+
+instance (Ix a, Eq b) => Eq (Array a b) where
+ a == a' = assocs a == assocs a'
+
+instance (Ix a, Ord b) => Ord (Array a b) where
+ a <= a' = assocs a <= assocs a'
+
+
+instance (Ix a, Show a, Show b) => Show (Array a b) where
+ showsPrec p a = showParen (p > 9) (
+ showString "array " .
+ shows (bounds a) . showChar ' ' .
+ shows (assocs a) )
+
+instance (Ix a, Read a, Read b) => Read (Array a b) where
+ readsPrec p = readParen (p > 9)
+ (\r -> [(array b as, u) | ("array",s) <- lex r,
+ (b,t) <- reads s,
+ (as,u) <- reads t ])
+#endif /* __HUGS__ */
diff --git a/libraries/base/Data/Array/Base.hs b/libraries/base/Data/Array/Base.hs
new file mode 100644
index 0000000000..7821876159
--- /dev/null
+++ b/libraries/base/Data/Array/Base.hs
@@ -0,0 +1,1163 @@
+{-# OPTIONS -monly-3-regs #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Array.Base
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Base.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Basis for IArray and MArray. Not intended for external consumption;
+-- use IArray or MArray instead.
+--
+-----------------------------------------------------------------------------
+
+module Data.Array.Base where
+
+import Prelude
+
+import Data.Ix ( Ix, range, index, rangeSize )
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Arr ( STArray, unsafeIndex )
+import qualified GHC.Arr
+import GHC.ST ( ST(..), runST )
+import GHC.Base
+import GHC.Word ( Word(..) )
+import GHC.Ptr ( Ptr(..), FunPtr(..) )
+import GHC.Float ( Float(..), Double(..) )
+import GHC.Stable ( StablePtr(..) )
+import GHC.Int ( Int8(..), Int16(..), Int32(..), Int64(..) )
+import GHC.Word ( Word8(..), Word16(..), Word32(..), Word64(..) )
+#endif
+
+import Data.Dynamic
+#include "Dynamic.h"
+
+-----------------------------------------------------------------------------
+-- Class of immutable arrays
+
+class HasBounds a where
+ bounds :: Ix i => a i e -> (i,i)
+
+class HasBounds a => IArray a e where
+ unsafeArray :: Ix i => (i,i) -> [(Int, e)] -> a i e
+ unsafeAt :: Ix i => a i e -> Int -> e
+ unsafeReplace :: Ix i => a i e -> [(Int, e)] -> a i e
+ unsafeAccum :: Ix i => (e -> e' -> e) -> a i e -> [(Int, e')] -> a i e
+ unsafeAccumArray :: Ix i => (e -> e' -> e) -> e -> (i,i) -> [(Int, e')] -> a i e
+
+ unsafeReplace arr ies = runST (unsafeReplaceST arr ies >>= unsafeFreeze)
+ unsafeAccum f arr ies = runST (unsafeAccumST f arr ies >>= unsafeFreeze)
+ unsafeAccumArray f e lu ies = runST (unsafeAccumArrayST f e lu ies >>= unsafeFreeze)
+
+{-# INLINE unsafeReplaceST #-}
+unsafeReplaceST :: (IArray a e, Ix i) => a i e -> [(Int, e)] -> ST s (STArray s i e)
+unsafeReplaceST arr ies = do
+ marr <- thaw arr
+ sequence_ [unsafeWrite marr i e | (i, e) <- ies]
+ return marr
+
+{-# INLINE unsafeAccumST #-}
+unsafeAccumST :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(Int, e')] -> ST s (STArray s i e)
+unsafeAccumST f arr ies = do
+ marr <- thaw arr
+ sequence_ [do
+ old <- unsafeRead marr i
+ unsafeWrite marr i (f old new)
+ | (i, new) <- ies]
+ return marr
+
+{-# INLINE unsafeAccumArrayST #-}
+unsafeAccumArrayST :: Ix i => (e -> e' -> e) -> e -> (i,i) -> [(Int, e')] -> ST s (STArray s i e)
+unsafeAccumArrayST f e (l,u) ies = do
+ marr <- newArray (l,u) e
+ sequence_ [do
+ old <- unsafeRead marr i
+ unsafeWrite marr i (f old new)
+ | (i, new) <- ies]
+ return marr
+
+{-# INLINE array #-}
+array :: (IArray a e, Ix i) => (i,i) -> [(i, e)] -> a i e
+array (l,u) ies = unsafeArray (l,u) [(index (l,u) i, e) | (i, e) <- ies]
+
+-- Since unsafeFreeze is not guaranteed to be only a cast, we will
+-- use unsafeArray and zip instead of a specialized loop to implement
+-- listArray, unlike Array.listArray, even though it generates some
+-- unnecessary heap allocation. Will use the loop only when we have
+-- fast unsafeFreeze, namely for Array and UArray (well, they cover
+-- almost all cases).
+
+{-# INLINE listArray #-}
+listArray :: (IArray a e, Ix i) => (i,i) -> [e] -> a i e
+listArray (l,u) es = unsafeArray (l,u) (zip [0 .. rangeSize (l,u) - 1] es)
+
+{-# INLINE listArrayST #-}
+listArrayST :: Ix i => (i,i) -> [e] -> ST s (STArray s i e)
+listArrayST (l,u) es = do
+ marr <- newArray_ (l,u)
+ let n = rangeSize (l,u)
+ let fillFromList i xs | i == n = return ()
+ | otherwise = case xs of
+ [] -> return ()
+ y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
+ fillFromList 0 es
+ return marr
+
+{-# RULES
+"listArray/Array" listArray =
+ \lu es -> runST (listArrayST lu es >>= GHC.Arr.unsafeFreezeSTArray)
+ #-}
+
+{-# INLINE listUArrayST #-}
+listUArrayST :: (MArray (STUArray s) e (ST s), Ix i)
+ => (i,i) -> [e] -> ST s (STUArray s i e)
+listUArrayST (l,u) es = do
+ marr <- newArray_ (l,u)
+ let n = rangeSize (l,u)
+ let fillFromList i xs | i == n = return ()
+ | otherwise = case xs of
+ [] -> return ()
+ y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
+ fillFromList 0 es
+ return marr
+
+-- I don't know how to write a single rule for listUArrayST, because
+-- the type looks like constrained over 's', which runST doesn't
+-- like. In fact all MArray (STUArray s) instances are polymorphic
+-- wrt. 's', but runST can't know that.
+
+-- I would like to write a rule for listUArrayST (or listArray or
+-- whatever) applied to unpackCString#. Unfortunately unpackCString#
+-- calls seem to be floated out, then floated back into the middle
+-- of listUArrayST, so I was not able to do this.
+
+{-# RULES
+"listArray/UArray/Bool" listArray = \lu (es :: [Bool]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Char" listArray = \lu (es :: [Char]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Int" listArray = \lu (es :: [Int]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Word" listArray = \lu (es :: [Word]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Ptr" listArray = \lu (es :: [Ptr a]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/FunPtr" listArray = \lu (es :: [FunPtr a]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Float" listArray = \lu (es :: [Float]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Double" listArray = \lu (es :: [Double]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/StablePtr" listArray = \lu (es :: [StablePtr a]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Int8" listArray = \lu (es :: [Int8]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Int16" listArray = \lu (es :: [Int16]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Int32" listArray = \lu (es :: [Int32]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Int64" listArray = \lu (es :: [Int64]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Word8" listArray = \lu (es :: [Word8]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Word16" listArray = \lu (es :: [Word16]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Word32" listArray = \lu (es :: [Word32]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+"listArray/UArray/Word64" listArray = \lu (es :: [Word64]) ->
+ runST (listUArrayST lu es >>= unsafeFreezeSTUArray)
+ #-}
+
+{-# INLINE (!) #-}
+(!) :: (IArray a e, Ix i) => a i e -> i -> e
+arr ! i | (l,u) <- bounds arr = unsafeAt arr (index (l,u) i)
+
+{-# INLINE indices #-}
+indices :: (HasBounds a, Ix i) => a i e -> [i]
+indices arr | (l,u) <- bounds arr = range (l,u)
+
+{-# INLINE elems #-}
+elems :: (IArray a e, Ix i) => a i e -> [e]
+elems arr | (l,u) <- bounds arr =
+ [unsafeAt arr i | i <- [0 .. rangeSize (l,u) - 1]]
+
+{-# INLINE assocs #-}
+assocs :: (IArray a e, Ix i) => a i e -> [(i, e)]
+assocs arr | (l,u) <- bounds arr =
+ [(i, unsafeAt arr (unsafeIndex (l,u) i)) | i <- range (l,u)]
+
+{-# INLINE accumArray #-}
+accumArray :: (IArray a e, Ix i) => (e -> e' -> e) -> e -> (i,i) -> [(i, e')] -> a i e
+accumArray f init (l,u) ies =
+ unsafeAccumArray f init (l,u) [(index (l,u) i, e) | (i, e) <- ies]
+
+{-# INLINE (//) #-}
+(//) :: (IArray a e, Ix i) => a i e -> [(i, e)] -> a i e
+arr // ies | (l,u) <- bounds arr =
+ unsafeReplace arr [(index (l,u) i, e) | (i, e) <- ies]
+
+{-# INLINE accum #-}
+accum :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(i, e')] -> a i e
+accum f arr ies | (l,u) <- bounds arr =
+ unsafeAccum f arr [(index (l,u) i, e) | (i, e) <- ies]
+
+{-# INLINE amap #-}
+amap :: (IArray a e', IArray a e, Ix i) => (e' -> e) -> a i e' -> a i e
+amap f arr | (l,u) <- bounds arr =
+ unsafeArray (l,u) [(i, f (unsafeAt arr i)) | i <- [0 .. rangeSize (l,u) - 1]]
+
+{-# INLINE ixmap #-}
+ixmap :: (IArray a e, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> a i e
+ixmap (l,u) f arr =
+ unsafeArray (l,u) [(unsafeIndex (l,u) i, arr ! f i) | i <- range (l,u)]
+
+-----------------------------------------------------------------------------
+-- Normal polymorphic arrays
+
+instance HasBounds GHC.Arr.Array where
+ {-# INLINE bounds #-}
+ bounds = GHC.Arr.bounds
+
+instance IArray GHC.Arr.Array e where
+ {-# INLINE unsafeArray #-}
+ unsafeArray = GHC.Arr.unsafeArray
+ {-# INLINE unsafeAt #-}
+ unsafeAt = GHC.Arr.unsafeAt
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace = GHC.Arr.unsafeReplace
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum = GHC.Arr.unsafeAccum
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray = GHC.Arr.unsafeAccumArray
+
+-----------------------------------------------------------------------------
+-- Flat unboxed arrays
+
+data UArray i e = UArray !i !i ByteArray#
+
+INSTANCE_TYPEABLE2(UArray,uArrayTc,"UArray")
+
+instance HasBounds UArray where
+ {-# INLINE bounds #-}
+ bounds (UArray l u _) = (l,u)
+
+{-# INLINE unsafeArrayUArray #-}
+unsafeArrayUArray :: (MArray (STUArray s) e (ST s), Ix i)
+ => (i,i) -> [(Int, e)] -> ST s (UArray i e)
+unsafeArrayUArray (l,u) ies = do
+ marr <- newArray_ (l,u)
+ sequence_ [unsafeWrite marr i e | (i, e) <- ies]
+ unsafeFreezeSTUArray marr
+
+{-# INLINE unsafeFreezeSTUArray #-}
+unsafeFreezeSTUArray :: STUArray s i e -> ST s (UArray i e)
+unsafeFreezeSTUArray (STUArray l u marr#) = ST $ \s1# ->
+ case unsafeFreezeByteArray# marr# s1# of { (# s2#, arr# #) ->
+ (# s2#, UArray l u arr# #) }
+
+{-# INLINE unsafeReplaceUArray #-}
+unsafeReplaceUArray :: (MArray (STUArray s) e (ST s), Ix i)
+ => UArray i e -> [(Int, e)] -> ST s (UArray i e)
+unsafeReplaceUArray arr ies = do
+ marr <- thawSTUArray arr
+ sequence_ [unsafeWrite marr i e | (i, e) <- ies]
+ unsafeFreezeSTUArray marr
+
+{-# INLINE unsafeAccumUArray #-}
+unsafeAccumUArray :: (MArray (STUArray s) e (ST s), Ix i)
+ => (e -> e' -> e) -> UArray i e -> [(Int, e')] -> ST s (UArray i e)
+unsafeAccumUArray f arr ies = do
+ marr <- thawSTUArray arr
+ sequence_ [do
+ old <- unsafeRead marr i
+ unsafeWrite marr i (f old new)
+ | (i, new) <- ies]
+ unsafeFreezeSTUArray marr
+
+{-# INLINE unsafeAccumArrayUArray #-}
+unsafeAccumArrayUArray :: (MArray (STUArray s) e (ST s), Ix i)
+ => (e -> e' -> e) -> e -> (i,i) -> [(Int, e')] -> ST s (UArray i e)
+unsafeAccumArrayUArray f init (l,u) ies = do
+ marr <- newArray (l,u) init
+ sequence_ [do
+ old <- unsafeRead marr i
+ unsafeWrite marr i (f old new)
+ | (i, new) <- ies]
+ unsafeFreezeSTUArray marr
+
+{-# INLINE eqUArray #-}
+eqUArray :: (IArray UArray e, Ix i, Eq e) => UArray i e -> UArray i e -> Bool
+eqUArray arr1@(UArray l1 u1 _) arr2@(UArray l2 u2 _) =
+ if rangeSize (l1,u1) == 0 then rangeSize (l2,u2) == 0 else
+ l1 == l2 && u1 == u2 &&
+ and [unsafeAt arr1 i == unsafeAt arr2 i | i <- [0 .. rangeSize (l1,u1) - 1]]
+
+{-# INLINE cmpUArray #-}
+cmpUArray :: (IArray UArray e, Ix i, Ord e) => UArray i e -> UArray i e -> Ordering
+cmpUArray arr1 arr2 = compare (assocs arr1) (assocs arr2)
+
+{-# INLINE cmpIntUArray #-}
+cmpIntUArray :: (IArray UArray e, Ord e) => UArray Int e -> UArray Int e -> Ordering
+cmpIntUArray arr1@(UArray l1 u1 _) arr2@(UArray l2 u2 _) =
+ if rangeSize (l1,u1) == 0 then if rangeSize (l2,u2) == 0 then EQ else LT else
+ if rangeSize (l2,u2) == 0 then GT else
+ case compare l1 l2 of
+ EQ -> foldr cmp (compare u1 u2) [0 .. rangeSize (l1, min u1 u2) - 1]
+ other -> other
+ where
+ cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of
+ EQ -> rest
+ other -> other
+
+{-# RULES "cmpUArray/Int" cmpUArray = cmpIntUArray #-}
+
+showsUArray :: (IArray UArray e, Ix i, Show i, Show e)
+ => Int -> UArray i e -> ShowS
+showsUArray p a =
+ showParen (p > 9) $
+ showString "array " .
+ shows (bounds a) .
+ showChar ' ' .
+ shows (assocs a)
+
+-----------------------------------------------------------------------------
+-- Flat unboxed arrays: instances
+
+instance IArray UArray Bool where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) =
+ (indexWordArray# arr# (bOOL_INDEX i#) `and#` bOOL_BIT i#)
+ `neWord#` int2Word# 0#
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Char where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = C# (indexWideCharArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Int where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = I# (indexIntArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Word where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = W# (indexWordArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray (Ptr a) where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = Ptr (indexAddrArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray (FunPtr a) where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = FunPtr (indexAddrArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Float where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = F# (indexFloatArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Double where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = D# (indexDoubleArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray (StablePtr a) where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = StablePtr (indexStablePtrArray# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Int8 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = I8# (indexInt8Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Int16 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = I16# (indexInt16Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Int32 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = I32# (indexInt32Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Int64 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = I64# (indexInt64Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Word8 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = W8# (indexWord8Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Word16 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = W16# (indexWord16Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Word32 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = W32# (indexWord32Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance IArray UArray Word64 where
+ {-# INLINE unsafeArray #-}
+ unsafeArray lu ies = runST (unsafeArrayUArray lu ies)
+ {-# INLINE unsafeAt #-}
+ unsafeAt (UArray _ _ arr#) (I# i#) = W64# (indexWord64Array# arr# i#)
+ {-# INLINE unsafeReplace #-}
+ unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
+ {-# INLINE unsafeAccum #-}
+ unsafeAccum f arr ies = runST (unsafeAccumUArray f arr ies)
+ {-# INLINE unsafeAccumArray #-}
+ unsafeAccumArray f init lu ies = runST (unsafeAccumArrayUArray f init lu ies)
+
+instance Ix ix => Eq (UArray ix Bool) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Char) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Int) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Word) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix (Ptr a)) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix (FunPtr a)) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Float) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Double) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix (StablePtr a)) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Int8) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Int16) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Int32) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Int64) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Word8) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Word16) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Word32) where
+ (==) = eqUArray
+
+instance Ix ix => Eq (UArray ix Word64) where
+ (==) = eqUArray
+
+instance Ix ix => Ord (UArray ix Bool) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Char) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Int) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Word) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix (Ptr a)) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix (FunPtr a)) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Float) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Double) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Int8) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Int16) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Int32) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Int64) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Word8) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Word16) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Word32) where
+ compare = cmpUArray
+
+instance Ix ix => Ord (UArray ix Word64) where
+ compare = cmpUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Bool) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Char) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Int) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Word) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Float) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Double) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Int8) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Int16) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Int32) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Int64) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Word8) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Word16) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Word32) where
+ showsPrec = showsUArray
+
+instance (Ix ix, Show ix) => Show (UArray ix Word64) where
+ showsPrec = showsUArray
+
+-----------------------------------------------------------------------------
+-- Mutable arrays
+
+{-# NOINLINE arrEleBottom #-}
+arrEleBottom :: a
+arrEleBottom = error "MArray: undefined array element"
+
+class (HasBounds a, Monad m) => MArray a e m where
+ newArray :: Ix i => (i,i) -> e -> m (a i e)
+ newArray_ :: Ix i => (i,i) -> m (a i e)
+ unsafeRead :: Ix i => a i e -> Int -> m e
+ unsafeWrite :: Ix i => a i e -> Int -> e -> m ()
+
+ newArray (l,u) init = do
+ marr <- newArray_ (l,u)
+ sequence_ [unsafeWrite marr i init | i <- [0 .. rangeSize (l,u) - 1]]
+ return marr
+
+ newArray_ (l,u) = newArray (l,u) arrEleBottom
+
+ -- newArray takes an initialiser which all elements of
+ -- the newly created array are initialised to. newArray_ takes
+ -- no initialiser, it is assumed that the array is initialised with
+ -- "undefined" values.
+
+ -- why not omit newArray_? Because in the unboxed array case we would
+ -- like to omit the initialisation altogether if possible. We can't do
+ -- this for boxed arrays, because the elements must all have valid values
+ -- at all times in case of garbage collection.
+
+ -- why not omit newArray? Because in the boxed case, we can omit the
+ -- default initialisation with undefined values if we *do* know the
+ -- initial value and it is constant for all elements.
+
+{-# INLINE newListArray #-}
+newListArray :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
+newListArray (l,u) es = do
+ marr <- newArray_ (l,u)
+ let n = rangeSize (l,u)
+ let fillFromList i xs | i == n = return ()
+ | otherwise = case xs of
+ [] -> return ()
+ y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
+ fillFromList 0 es
+ return marr
+
+{-# INLINE readArray #-}
+readArray :: (MArray a e m, Ix i) => a i e -> i -> m e
+readArray marr i | (l,u) <- bounds marr =
+ unsafeRead marr (index (l,u) i)
+
+{-# INLINE writeArray #-}
+writeArray :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
+writeArray marr i e | (l,u) <- bounds marr =
+ unsafeWrite marr (index (l,u) i) e
+
+{-# INLINE getElems #-}
+getElems :: (MArray a e m, Ix i) => a i e -> m [e]
+getElems marr | (l,u) <- bounds marr =
+ sequence [unsafeRead marr i | i <- [0 .. rangeSize (l,u) - 1]]
+
+{-# INLINE getAssocs #-}
+getAssocs :: (MArray a e m, Ix i) => a i e -> m [(i, e)]
+getAssocs marr | (l,u) <- bounds marr =
+ sequence [do e <- unsafeRead marr (index (l,u) i); return (i,e)
+ | i <- range (l,u)]
+
+{-# INLINE mapArray #-}
+mapArray :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)
+mapArray f marr | (l,u) <- bounds marr = do
+ marr' <- newArray_ (l,u)
+ sequence_ [do
+ e <- unsafeRead marr i
+ unsafeWrite marr' i (f e)
+ | i <- [0 .. rangeSize (l,u) - 1]]
+ return marr'
+
+{-# INLINE mapIndices #-}
+mapIndices :: (MArray a e m, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> m (a i e)
+mapIndices (l,u) f marr = do
+ marr' <- newArray_ (l,u)
+ sequence_ [do
+ e <- readArray marr (f i)
+ unsafeWrite marr' (unsafeIndex (l,u) i) e
+ | i <- range (l,u)]
+ return marr'
+
+-----------------------------------------------------------------------------
+-- Polymorphic non-strict mutable arrays (ST monad)
+
+instance HasBounds (STArray s) where
+ {-# INLINE bounds #-}
+ bounds = GHC.Arr.boundsSTArray
+
+instance MArray (STArray s) e (ST s) where
+ {-# INLINE newArray #-}
+ newArray = GHC.Arr.newSTArray
+ {-# INLINE unsafeRead #-}
+ unsafeRead = GHC.Arr.unsafeReadSTArray
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite = GHC.Arr.unsafeWriteSTArray
+
+-----------------------------------------------------------------------------
+-- Typeable instance for STArray
+
+sTArrayTc :: TyCon
+sTArrayTc = mkTyCon "STArray"
+
+instance (Typeable a, Typeable b, Typeable c) => Typeable (STArray a b c) where
+ typeOf a = mkAppTy sTArrayTc [typeOf ((undefined :: STArray a b c -> a) a),
+ typeOf ((undefined :: STArray a b c -> b) a),
+ typeOf ((undefined :: STArray a b c -> c) a)]
+
+-----------------------------------------------------------------------------
+-- Flat unboxed mutable arrays (ST monad)
+
+data STUArray s i a = STUArray !i !i (MutableByteArray# s)
+
+INSTANCE_TYPEABLE3(STUArray,stUArrayTc,"STUArray")
+
+instance HasBounds (STUArray s) where
+ {-# INLINE bounds #-}
+ bounds (STUArray l u _) = (l,u)
+
+instance MArray (STUArray s) Bool (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (bOOL_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readWordArray# marr# (bOOL_INDEX i#) s1# of { (# s2#, e# #) ->
+ (# s2#, (e# `and#` bOOL_BIT i#) `neWord#` int2Word# 0# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) e = ST $ \s1# ->
+ case bOOL_INDEX i# of { j# ->
+ case readWordArray# marr# j# s1# of { (# s2#, old# #) ->
+ case if e then old# `or#` bOOL_BIT i#
+ else old# `and#` bOOL_NOT_BIT i# of { e# ->
+ case writeWordArray# marr# j# e# s2# of { s3# ->
+ (# s3#, () #) }}}}
+
+instance MArray (STUArray s) Char (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (n# *# 4#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readWideCharArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, C# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (C# e#) = ST $ \s1# ->
+ case writeWideCharArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Int (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (wORD_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readIntArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, I# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (I# e#) = ST $ \s1# ->
+ case writeIntArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Word (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (wORD_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readWordArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, W# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (W# e#) = ST $ \s1# ->
+ case writeWordArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) (Ptr a) (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (wORD_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readAddrArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, Ptr e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (Ptr e#) = ST $ \s1# ->
+ case writeAddrArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) (FunPtr a) (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (wORD_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readAddrArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, FunPtr e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (FunPtr e#) = ST $ \s1# ->
+ case writeAddrArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Float (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (fLOAT_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readFloatArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, F# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (F# e#) = ST $ \s1# ->
+ case writeFloatArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Double (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (dOUBLE_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readDoubleArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, D# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (D# e#) = ST $ \s1# ->
+ case writeDoubleArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) (StablePtr a) (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (wORD_SCALE n#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readStablePtrArray# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2# , StablePtr e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (StablePtr e#) = ST $ \s1# ->
+ case writeStablePtrArray# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Int8 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# n# s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readInt8Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, I8# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (I8# e#) = ST $ \s1# ->
+ case writeInt8Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Int16 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (n# *# 2#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readInt16Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, I16# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (I16# e#) = ST $ \s1# ->
+ case writeInt16Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Int32 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (n# *# 4#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readInt32Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, I32# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (I32# e#) = ST $ \s1# ->
+ case writeInt32Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Int64 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (n# *# 8#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readInt64Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, I64# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (I64# e#) = ST $ \s1# ->
+ case writeInt64Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Word8 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# n# s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readWord8Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, W8# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (W8# e#) = ST $ \s1# ->
+ case writeWord8Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Word16 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (n# *# 2#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readWord16Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, W16# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (W16# e#) = ST $ \s1# ->
+ case writeWord16Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Word32 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (n# *# 4#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readWord32Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, W32# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (W32# e#) = ST $ \s1# ->
+ case writeWord32Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+instance MArray (STUArray s) Word64 (ST s) where
+ {-# INLINE newArray_ #-}
+ newArray_ (l,u) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newByteArray# (n# *# 8#) s1# of { (# s2#, marr# #) ->
+ (# s2#, STUArray l u marr# #) }}
+ {-# INLINE unsafeRead #-}
+ unsafeRead (STUArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ case readWord64Array# marr# i# s1# of { (# s2#, e# #) ->
+ (# s2#, W64# e# #) }
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (STUArray _ _ marr#) (I# i#) (W64# e#) = ST $ \s1# ->
+ case writeWord64Array# marr# i# e# s1# of { s2# ->
+ (# s2#, () #) }
+
+-----------------------------------------------------------------------------
+-- Translation between elements and bytes
+
+#include "config.h"
+
+bOOL_SCALE, wORD_SCALE, dOUBLE_SCALE, fLOAT_SCALE :: Int# -> Int#
+bOOL_SCALE n# = bOOL_INDEX (n# +# last#) where I# last# = SIZEOF_VOID_P - 1
+wORD_SCALE n# = scale# *# n# where I# scale# = SIZEOF_VOID_P
+dOUBLE_SCALE n# = scale# *# n# where I# scale# = SIZEOF_DOUBLE
+fLOAT_SCALE n# = scale# *# n# where I# scale# = SIZEOF_FLOAT
+
+bOOL_INDEX :: Int# -> Int#
+#if SIZEOF_VOID_P == 4
+bOOL_INDEX i# = i# `iShiftRA#` 5#
+#else
+bOOL_INDEX i# = i# `iShiftRA#` 6#
+#endif
+
+bOOL_BIT, bOOL_NOT_BIT :: Int# -> Word#
+bOOL_BIT n# = int2Word# 1# `shiftL#` (word2Int# (int2Word# n# `and#` mask#))
+ where W# mask# = SIZEOF_VOID_P * 8 - 1
+bOOL_NOT_BIT n# = bOOL_BIT n# `xor#` mb# where W# mb# = maxBound
+
+-----------------------------------------------------------------------------
+-- Freezing
+
+freeze :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)
+freeze marr | (l,u) <- bounds marr = do
+ ies <- sequence [do e <- unsafeRead marr i; return (i,e)
+ | i <- [0 .. rangeSize (l,u) - 1]]
+ return (unsafeArray (l,u) ies)
+
+freezeSTUArray :: Ix i => STUArray s i e -> ST s (UArray i e)
+freezeSTUArray (STUArray l u marr#) = ST $ \s1# ->
+ case sizeofMutableByteArray# marr# of { n# ->
+ case newByteArray# n# s1# of { (# s2#, marr'# #) ->
+ case unsafeCoerce# memcpy marr'# marr# n# s2# of { (# s3#, () #) ->
+ case unsafeFreezeByteArray# marr'# s3# of { (# s4#, arr# #) ->
+ (# s4#, UArray l u arr# #) }}}}
+
+{-# RULES
+"freeze/STArray" freeze = GHC.Arr.freezeSTArray
+"freeze/STUArray" freeze = freezeSTUArray
+ #-}
+
+-- In-place conversion of mutable arrays to immutable ones places
+-- a proof obligation on the user: no other parts of your code can
+-- have a reference to the array at the point where you unsafely
+-- freeze it (and, subsequently mutate it, I suspect).
+
+{-# INLINE unsafeFreeze #-}
+unsafeFreeze :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)
+unsafeFreeze = freeze
+
+{-# RULES
+"unsafeFreeze/STArray" unsafeFreeze = GHC.Arr.unsafeFreezeSTArray
+"unsafeFreeze/STUArray" unsafeFreeze = unsafeFreezeSTUArray
+ #-}
+
+-----------------------------------------------------------------------------
+-- Thawing
+
+thaw :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
+thaw arr | (l,u) <- bounds arr = do
+ marr <- newArray_ (l,u)
+ sequence_ [unsafeWrite marr i (unsafeAt arr i)
+ | i <- [0 .. rangeSize (l,u) - 1]]
+ return marr
+
+thawSTUArray :: Ix i => UArray i e -> ST s (STUArray s i e)
+thawSTUArray (UArray l u arr#) = ST $ \s1# ->
+ case sizeofByteArray# arr# of { n# ->
+ case newByteArray# n# s1# of { (# s2#, marr# #) ->
+ case unsafeCoerce# memcpy marr# arr# n# s2# of { (# s3#, () #) ->
+ (# s3#, STUArray l u marr# #) }}}
+
+foreign import "memcpy" unsafe
+ memcpy :: MutableByteArray# RealWorld -> ByteArray# -> Int# -> IO ()
+
+{-# RULES
+"thaw/STArray" thaw = GHC.Arr.thawSTArray
+"thaw/STUArray" thaw = thawSTUArray
+ #-}
+
+-- In-place conversion of immutable arrays to mutable ones places
+-- a proof obligation on the user: no other parts of your code can
+-- have a reference to the array at the point where you unsafely
+-- thaw it (and, subsequently mutate it, I suspect).
+
+{-# INLINE unsafeThaw #-}
+unsafeThaw :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
+unsafeThaw = thaw
+
+{-# INLINE unsafeThawSTUArray #-}
+unsafeThawSTUArray :: Ix i => UArray i e -> ST s (STUArray s i e)
+unsafeThawSTUArray (UArray l u marr#) =
+ return (STUArray l u (unsafeCoerce# marr#))
+
+{-# RULES
+"unsafeThaw/STArray" unsafeThaw = GHC.Arr.unsafeThawSTArray
+"unsafeThaw/STUArray" unsafeThaw = unsafeThawSTUArray
+ #-}
diff --git a/libraries/base/Data/Array/IArray.hs b/libraries/base/Data/Array/IArray.hs
new file mode 100644
index 0000000000..b97daeec6a
--- /dev/null
+++ b/libraries/base/Data/Array/IArray.hs
@@ -0,0 +1,42 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Array.IArray
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: IArray.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Overloaded immutable array class.
+--
+-----------------------------------------------------------------------------
+
+module Data.Array.IArray (
+ module Data.Ix,
+
+ -- Class of immutable array types
+ IArray, -- :: (* -> * -> *) -> * -> class
+ -- Class of array types with immutable bounds
+ HasBounds, -- :: (* -> * -> *) -> class
+
+ array, -- :: (IArray a e, Ix i) => (i,i) -> [(i, e)] -> a i e
+ listArray, -- :: (IArray a e, Ix i) => (i,i) -> [e] -> a i e
+ (!), -- :: (IArray a e, Ix i) => a i e -> i -> e
+ bounds, -- :: (HasBounds a, Ix i) => a i e -> (i,i)
+ indices, -- :: (HasBounds a, Ix i) => a i e -> [i]
+ elems, -- :: (IArray a e, Ix i) => a i e -> [e]
+ assocs, -- :: (IArray a e, Ix i) => a i e -> [(i, e)]
+ accumArray, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> e -> (i,i) -> [(i, e')] -> a i e
+ (//), -- :: (IArray a e, Ix i) => a i e -> [(i, e)] -> a i e
+ accum, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(i, e')] -> a i e
+ amap, -- :: (IArray a e', IArray a e, Ix i) => (e' -> e) -> a i e' -> a i e
+ ixmap) -- :: (IArray a e, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> a i e
+ where
+
+import Prelude
+
+import Data.Ix
+import Data.Array.Base
diff --git a/libraries/base/Data/Array/IO.hs b/libraries/base/Data/Array/IO.hs
new file mode 100644
index 0000000000..9e7892ef50
--- /dev/null
+++ b/libraries/base/Data/Array/IO.hs
@@ -0,0 +1,365 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Array.IO
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: IO.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Mutable boxed/unboxed arrays in the IO monad.
+--
+-----------------------------------------------------------------------------
+
+module Data.Array.IO (
+ module Data.Array.MArray,
+ IOArray, -- instance of: Eq, Typeable
+ IOUArray, -- instance of: Eq, Typeable
+ castIOUArray, -- :: IOUArray i a -> IO (IOUArray i b)
+ ) where
+
+import Prelude
+
+import Data.Array ( Array )
+import Data.Array.MArray
+import Data.Int
+import Data.Word
+import Data.Dynamic
+
+import Foreign.Ptr ( Ptr, FunPtr )
+import Foreign.StablePtr ( StablePtr )
+
+#ifdef __GLASGOW_HASKELL__
+-- GHC only to the end of file
+
+import Data.Array.Base
+import GHC.Arr ( STArray, freezeSTArray, unsafeFreezeSTArray,
+ thawSTArray, unsafeThawSTArray )
+
+import GHC.ST ( ST(..) )
+import GHC.IOBase ( stToIO )
+
+import GHC.Base
+
+-----------------------------------------------------------------------------
+-- Polymorphic non-strict mutable arrays (IO monad)
+
+newtype IOArray i e = IOArray (STArray RealWorld i e) deriving Eq
+
+iOArrayTc :: TyCon
+iOArrayTc = mkTyCon "IOArray"
+
+instance (Typeable a, Typeable b) => Typeable (IOArray a b) where
+ typeOf a = mkAppTy iOArrayTc [typeOf ((undefined :: IOArray a b -> a) a),
+ typeOf ((undefined :: IOArray a b -> b) a)]
+
+instance HasBounds IOArray where
+ {-# INLINE bounds #-}
+ bounds (IOArray marr) = bounds marr
+
+instance MArray IOArray e IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOArray marr) i e = stToIO (unsafeWrite marr i e)
+
+-----------------------------------------------------------------------------
+-- Flat unboxed mutable arrays (IO monad)
+
+newtype IOUArray i e = IOUArray (STUArray RealWorld i e) deriving Eq
+
+iOUArrayTc :: TyCon
+iOUArrayTc = mkTyCon "IOUArray"
+
+instance (Typeable a, Typeable b) => Typeable (IOUArray a b) where
+ typeOf a = mkAppTy iOUArrayTc [typeOf ((undefined :: IOUArray a b -> a) a),
+ typeOf ((undefined :: IOUArray a b -> b) a)]
+
+instance HasBounds IOUArray where
+ {-# INLINE bounds #-}
+ bounds (IOUArray marr) = bounds marr
+
+instance MArray IOUArray Bool IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Char IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Int IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Word IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray (Ptr a) IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray (FunPtr a) IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Float IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Double IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray (StablePtr a) IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Int8 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Int16 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Int32 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Int64 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Word8 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Word16 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Word32 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+instance MArray IOUArray Word64 IO where
+ {-# INLINE newArray #-}
+ newArray lu init = stToIO $ do
+ marr <- newArray lu init; return (IOUArray marr)
+ {-# INLINE newArray_ #-}
+ newArray_ lu = stToIO $ do
+ marr <- newArray_ lu; return (IOUArray marr)
+ {-# INLINE unsafeRead #-}
+ unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
+ {-# INLINE unsafeWrite #-}
+ unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
+
+-----------------------------------------------------------------------------
+-- Freezing
+
+freezeIOArray :: Ix ix => IOArray ix e -> IO (Array ix e)
+freezeIOArray (IOArray marr) = stToIO (freezeSTArray marr)
+
+freezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
+freezeIOUArray (IOUArray marr) = stToIO (freezeSTUArray marr)
+
+{-# RULES
+"freeze/IOArray" freeze = freezeIOArray
+"freeze/IOUArray" freeze = freezeIOUArray
+ #-}
+
+{-# INLINE unsafeFreezeIOArray #-}
+unsafeFreezeIOArray :: Ix ix => IOArray ix e -> IO (Array ix e)
+unsafeFreezeIOArray (IOArray marr) = stToIO (unsafeFreezeSTArray marr)
+
+{-# INLINE unsafeFreezeIOUArray #-}
+unsafeFreezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
+unsafeFreezeIOUArray (IOUArray marr) = stToIO (unsafeFreezeSTUArray marr)
+
+{-# RULES
+"unsafeFreeze/IOArray" unsafeFreeze = unsafeFreezeIOArray
+"unsafeFreeze/IOUArray" unsafeFreeze = unsafeFreezeIOUArray
+ #-}
+
+-----------------------------------------------------------------------------
+-- Thawing
+
+thawIOArray :: Ix ix => Array ix e -> IO (IOArray ix e)
+thawIOArray arr = stToIO $ do
+ marr <- thawSTArray arr
+ return (IOArray marr)
+
+thawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
+thawIOUArray arr = stToIO $ do
+ marr <- thawSTUArray arr
+ return (IOUArray marr)
+
+{-# RULES
+"thaw/IOArray" thaw = thawIOArray
+"thaw/IOUArray" thaw = thawIOUArray
+ #-}
+
+{-# INLINE unsafeThawIOArray #-}
+unsafeThawIOArray :: Ix ix => Array ix e -> IO (IOArray ix e)
+unsafeThawIOArray arr = stToIO $ do
+ marr <- unsafeThawSTArray arr
+ return (IOArray marr)
+
+{-# INLINE unsafeThawIOUArray #-}
+unsafeThawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
+unsafeThawIOUArray arr = stToIO $ do
+ marr <- unsafeThawSTUArray arr
+ return (IOUArray marr)
+
+{-# RULES
+"unsafeThaw/IOArray" unsafeThaw = unsafeThawIOArray
+"unsafeThaw/IOUArray" unsafeThaw = unsafeThawIOUArray
+ #-}
+
+castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
+castSTUArray (STUArray l u marr#) = return (STUArray l u marr#)
+
+castIOUArray :: IOUArray ix a -> IO (IOUArray ix b)
+castIOUArray (IOUArray marr) = stToIO $ do
+ marr' <- castSTUArray marr
+ return (IOUArray marr')
+
+#endif /* __GLASGOW_HASKELL__ */
diff --git a/libraries/base/Data/Array/MArray.hs b/libraries/base/Data/Array/MArray.hs
new file mode 100644
index 0000000000..c341dab6da
--- /dev/null
+++ b/libraries/base/Data/Array/MArray.hs
@@ -0,0 +1,47 @@
+{-# OPTIONS -monly-3-regs #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Array.MArray
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: MArray.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Class of mutable arrays, and operations on them.
+--
+-----------------------------------------------------------------------------
+
+module Data.Array.MArray (
+ module Data.Ix,
+
+ -- Class of mutable array types
+ MArray, -- :: (* -> * -> *) -> * -> (* -> *) -> class
+ -- Class of array types with immutable bounds
+ HasBounds, -- :: (* -> * -> *) -> class
+
+ newArray, -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)
+ newArray_, -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)
+ newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
+ readArray, -- :: (MArray a e m, Ix i) => a i e -> i -> m e
+ writeArray, -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
+ bounds, -- :: (HasBounds a, Ix i) => a i e -> (i,i)
+ indices, -- :: (HasBounds a, Ix i) => a i e -> [i]
+ getElems, -- :: (MArray a e m, Ix i) => a i e -> m [e]
+ getAssocs, -- :: (MArray a e m, Ix i) => a i e -> m [(i, e)]
+ mapArray, -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)
+ mapIndices, -- :: (MArray a e m, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> m (a i e)
+
+ freeze, -- :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)
+ unsafeFreeze, -- :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)
+ thaw, -- :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
+ unsafeThaw, -- :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
+ ) where
+
+import Prelude
+
+import Data.Ix
+import Data.Array.Base
diff --git a/libraries/base/Data/Array/ST.hs b/libraries/base/Data/Array/ST.hs
new file mode 100644
index 0000000000..143f792df0
--- /dev/null
+++ b/libraries/base/Data/Array/ST.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Array.ST
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: ST.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Mutable boxed/unboxed arrays in the ST monad.
+--
+-----------------------------------------------------------------------------
+
+module Data.Array.ST (
+ module Data.Array.MArray,
+ STArray, -- instance of: Eq, MArray
+ STUArray, -- instance of: Eq, MArray
+ castSTUArray, -- :: STUArray s i a -> ST s (STUArray s i b)
+ ) where
+
+import Prelude
+
+import Data.Array.MArray
+import Data.Array.Base
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Arr
+import GHC.ST
+
+castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
+castSTUArray (STUArray l u marr#) = return (STUArray l u marr#)
+#endif
diff --git a/libraries/base/Data/Array/Unboxed.hs b/libraries/base/Data/Array/Unboxed.hs
new file mode 100644
index 0000000000..b4a0ecfc02
--- /dev/null
+++ b/libraries/base/Data/Array/Unboxed.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Array.Unboxed
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Unboxed.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Unboxed immutable array type.
+--
+-----------------------------------------------------------------------------
+
+module Data.Array.Unboxed (
+ module Data.Array.IArray,
+ UArray,
+ ) where
+
+import Prelude
+
+import Data.Array.IArray
+import Data.Array.Base
diff --git a/libraries/base/Data/Bits.hs b/libraries/base/Data/Bits.hs
new file mode 100644
index 0000000000..8a37e82bd9
--- /dev/null
+++ b/libraries/base/Data/Bits.hs
@@ -0,0 +1,143 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Bits
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Bits.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Bitwise operations.
+--
+-----------------------------------------------------------------------------
+
+module Data.Bits (
+ Bits(
+ (.&.), (.|.), xor, -- :: a -> a -> a
+ complement, -- :: a -> a
+ shift, -- :: a -> Int -> a
+ rotate, -- :: a -> Int -> a
+ bit, -- :: Int -> a
+ setBit, -- :: a -> Int -> a
+ clearBit, -- :: a -> Int -> a
+ complementBit, -- :: a -> Int -> a
+ testBit, -- :: a -> Int -> Bool
+ bitSize, -- :: a -> Int
+ isSigned -- :: a -> Bool
+ ),
+ shiftL, shiftR, -- :: Bits a => a -> Int -> a
+ rotateL, rotateR, -- :: Bits a => a -> Int -> a
+ -- instance Bits Int
+ -- instance Bits Integer
+ ) where
+
+-- Defines the @Bits@ class containing bit-based operations.
+-- See library document for details on the semantics of the
+-- individual operations.
+
+#ifdef __GLASGOW_HASKELL__
+#include "MachDeps.h"
+import GHC.Num
+import GHC.Real
+import GHC.Base
+#endif
+
+--ADR: The fixity for .|. conflicts with that for .|. in Fran.
+-- Removing all fixities is a fairly safe fix; fixing the "one fixity
+-- per symbol per program" limitation in Hugs would take a lot longer.
+#ifndef __HUGS__
+infixl 8 `shift`, `rotate`
+infixl 7 .&.
+infixl 6 `xor`
+infixl 5 .|.
+#endif
+
+class Num a => Bits a where
+ (.&.), (.|.), xor :: a -> a -> a
+ complement :: a -> a
+ shift :: a -> Int -> a
+ rotate :: a -> Int -> a
+ bit :: Int -> a
+ setBit :: a -> Int -> a
+ clearBit :: a -> Int -> a
+ complementBit :: a -> Int -> a
+ testBit :: a -> Int -> Bool
+ bitSize :: a -> Int
+ isSigned :: a -> Bool
+
+ bit i = 1 `shift` i
+ x `setBit` i = x .|. bit i
+ x `clearBit` i = x .&. complement (bit i)
+ x `complementBit` i = x `xor` bit i
+ x `testBit` i = (x .&. bit i) /= 0
+
+shiftL, shiftR :: Bits a => a -> Int -> a
+rotateL, rotateR :: Bits a => a -> Int -> a
+x `shiftL` i = x `shift` i
+x `shiftR` i = x `shift` (-i)
+x `rotateL` i = x `rotate` i
+x `rotateR` i = x `rotate` (-i)
+
+#ifdef __GLASGOW_HASKELL__
+instance Bits Int where
+ (I# x#) .&. (I# y#) = I# (word2Int# (int2Word# x# `and#` int2Word# y#))
+ (I# x#) .|. (I# y#) = I# (word2Int# (int2Word# x# `or#` int2Word# y#))
+ (I# x#) `xor` (I# y#) = I# (word2Int# (int2Word# x# `xor#` int2Word# y#))
+ complement (I# x#) = I# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))
+ (I# x#) `shift` (I# i#)
+ | i# >=# 0# = I# (x# `iShiftL#` i#)
+ | otherwise = I# (x# `iShiftRA#` negateInt# i#)
+ (I# x#) `rotate` (I# i#) =
+#if WORD_SIZE_IN_BYTES == 4
+ I# (word2Int# ((x'# `shiftL#` i'#) `or#`
+ (x'# `shiftRL#` (32# -# i'#))))
+ where
+ x'# = int2Word# x#
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 31#)
+#else
+ I# (word2Int# ((x'# `shiftL#` i'#) `or#`
+ (x'# `shiftRL#` (64# -# i'#))))
+ where
+ x'# = int2Word# x#
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)
+#endif
+ bitSize _ = WORD_SIZE_IN_BYTES * 8
+ isSigned _ = True
+
+instance Bits Integer where
+ (S# x) .&. (S# y) = S# (word2Int# (int2Word# x `and#` int2Word# y))
+ x@(S# _) .&. y = toBig x .&. y
+ x .&. y@(S# _) = x .&. toBig y
+ (J# s1 d1) .&. (J# s2 d2) =
+ case andInteger# s1 d1 s2 d2 of
+ (# s, d #) -> J# s d
+
+ (S# x) .|. (S# y) = S# (word2Int# (int2Word# x `or#` int2Word# y))
+ x@(S# _) .|. y = toBig x .|. y
+ x .|. y@(S# _) = x .|. toBig y
+ (J# s1 d1) .|. (J# s2 d2) =
+ case orInteger# s1 d1 s2 d2 of
+ (# s, d #) -> J# s d
+
+ (S# x) `xor` (S# y) = S# (word2Int# (int2Word# x `xor#` int2Word# y))
+ x@(S# _) `xor` y = toBig x `xor` y
+ x `xor` y@(S# _) = x `xor` toBig y
+ (J# s1 d1) `xor` (J# s2 d2) =
+ case xorInteger# s1 d1 s2 d2 of
+ (# s, d #) -> J# s d
+
+ complement (S# x) = S# (word2Int# (int2Word# x `xor#` int2Word# (0# -# 1#)))
+ complement (J# s d) = case complementInteger# s d of (# s, d #) -> J# s d
+
+ shift x i | i >= 0 = x * 2^i
+ | otherwise = x `div` 2^(-i)
+
+ rotate x i = shift x i -- since an Integer never wraps around
+
+ bitSize _ = error "Bits.bitSize(Integer)"
+ isSigned _ = True
+#endif
diff --git a/libraries/base/Data/Bool.hs b/libraries/base/Data/Bool.hs
new file mode 100644
index 0000000000..33804d2705
--- /dev/null
+++ b/libraries/base/Data/Bool.hs
@@ -0,0 +1,28 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Bool
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Bool.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Bool type and related functions.
+--
+-----------------------------------------------------------------------------
+
+module Data.Bool (
+ Bool(..),
+ (&&), -- :: Bool -> Bool -> Bool
+ (||), -- :: Bool -> Bool -> Bool
+ not, -- :: Bool -> Bool
+ otherwise, -- :: Bool
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+#endif
diff --git a/libraries/base/Data/Char.hs b/libraries/base/Data/Char.hs
new file mode 100644
index 0000000000..e0c9566f5f
--- /dev/null
+++ b/libraries/base/Data/Char.hs
@@ -0,0 +1,51 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Char
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Char.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Char type and associated operations.
+--
+-----------------------------------------------------------------------------
+
+module Data.Char
+ (
+ Char
+
+ , isAscii, isLatin1, isControl
+ , isPrint, isSpace, isUpper
+ , isLower, isAlpha, isDigit
+ , isOctDigit, isHexDigit, isAlphaNum -- :: Char -> Bool
+
+ , toUpper, toLower -- :: Char -> Char
+
+ , digitToInt -- :: Char -> Int
+ , intToDigit -- :: Int -> Char
+
+ , ord -- :: Char -> Int
+ , chr -- :: Int -> Char
+ , readLitChar -- :: ReadS Char
+ , showLitChar -- :: Char -> ShowS
+ , lexLitChar -- :: ReadS String
+
+ , String
+
+ -- Implementation checked wrt. Haskell 98 lib report, 1/99.
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.Show
+import GHC.Read (readLitChar, lexLitChar, digitToInt)
+#endif
+
+#ifdef __HUGS__
+isLatin1 c = True
+#endif
diff --git a/libraries/base/Data/Complex.hs b/libraries/base/Data/Complex.hs
new file mode 100644
index 0000000000..e132f2186c
--- /dev/null
+++ b/libraries/base/Data/Complex.hs
@@ -0,0 +1,153 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Complex
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Complex.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Complex numbers.
+--
+-----------------------------------------------------------------------------
+
+module Data.Complex
+ ( Complex((:+))
+
+ , realPart -- :: (RealFloat a) => Complex a -> a
+ , imagPart -- :: (RealFloat a) => Complex a -> a
+ , conjugate -- :: (RealFloat a) => Complex a -> Complex a
+ , mkPolar -- :: (RealFloat a) => a -> a -> Complex a
+ , cis -- :: (RealFloat a) => a -> Complex a
+ , polar -- :: (RealFloat a) => Complex a -> (a,a)
+ , magnitude -- :: (RealFloat a) => Complex a -> a
+ , phase -- :: (RealFloat a) => Complex a -> a
+
+ -- Complex instances:
+ --
+ -- (RealFloat a) => Eq (Complex a)
+ -- (RealFloat a) => Read (Complex a)
+ -- (RealFloat a) => Show (Complex a)
+ -- (RealFloat a) => Num (Complex a)
+ -- (RealFloat a) => Fractional (Complex a)
+ -- (RealFloat a) => Floating (Complex a)
+ --
+ -- Implementation checked wrt. Haskell 98 lib report, 1/99.
+
+ ) where
+
+import Prelude
+
+import Data.Dynamic
+
+infix 6 :+
+
+-- -----------------------------------------------------------------------------
+-- The Complex type
+
+data (RealFloat a) => Complex a = !a :+ !a deriving (Eq, Read, Show)
+
+
+-- -----------------------------------------------------------------------------
+-- Functions over Complex
+
+realPart, imagPart :: (RealFloat a) => Complex a -> a
+realPart (x :+ _) = x
+imagPart (_ :+ y) = y
+
+conjugate :: (RealFloat a) => Complex a -> Complex a
+conjugate (x:+y) = x :+ (-y)
+
+mkPolar :: (RealFloat a) => a -> a -> Complex a
+mkPolar r theta = r * cos theta :+ r * sin theta
+
+cis :: (RealFloat a) => a -> Complex a
+cis theta = cos theta :+ sin theta
+
+polar :: (RealFloat a) => Complex a -> (a,a)
+polar z = (magnitude z, phase z)
+
+magnitude :: (RealFloat a) => Complex a -> a
+magnitude (x:+y) = scaleFloat k
+ (sqrt ((scaleFloat mk x)^(2::Int) + (scaleFloat mk y)^(2::Int)))
+ where k = max (exponent x) (exponent y)
+ mk = - k
+
+phase :: (RealFloat a) => Complex a -> a
+phase (0 :+ 0) = 0 -- SLPJ July 97 from John Peterson
+phase (x:+y) = atan2 y x
+
+
+-- -----------------------------------------------------------------------------
+-- Instances of Complex
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE1(Complex,complexTc,"Complex")
+
+instance (RealFloat a) => Num (Complex a) where
+ {-# SPECIALISE instance Num (Complex Float) #-}
+ {-# SPECIALISE instance Num (Complex Double) #-}
+ (x:+y) + (x':+y') = (x+x') :+ (y+y')
+ (x:+y) - (x':+y') = (x-x') :+ (y-y')
+ (x:+y) * (x':+y') = (x*x'-y*y') :+ (x*y'+y*x')
+ negate (x:+y) = negate x :+ negate y
+ abs z = magnitude z :+ 0
+ signum 0 = 0
+ signum z@(x:+y) = x/r :+ y/r where r = magnitude z
+ fromInteger n = fromInteger n :+ 0
+
+instance (RealFloat a) => Fractional (Complex a) where
+ {-# SPECIALISE instance Fractional (Complex Float) #-}
+ {-# SPECIALISE instance Fractional (Complex Double) #-}
+ (x:+y) / (x':+y') = (x*x''+y*y'') / d :+ (y*x''-x*y'') / d
+ where x'' = scaleFloat k x'
+ y'' = scaleFloat k y'
+ k = - max (exponent x') (exponent y')
+ d = x'*x'' + y'*y''
+
+ fromRational a = fromRational a :+ 0
+
+instance (RealFloat a) => Floating (Complex a) where
+ {-# SPECIALISE instance Floating (Complex Float) #-}
+ {-# SPECIALISE instance Floating (Complex Double) #-}
+ pi = pi :+ 0
+ exp (x:+y) = expx * cos y :+ expx * sin y
+ where expx = exp x
+ log z = log (magnitude z) :+ phase z
+
+ sqrt 0 = 0
+ sqrt z@(x:+y) = u :+ (if y < 0 then -v else v)
+ where (u,v) = if x < 0 then (v',u') else (u',v')
+ v' = abs y / (u'*2)
+ u' = sqrt ((magnitude z + abs x) / 2)
+
+ sin (x:+y) = sin x * cosh y :+ cos x * sinh y
+ cos (x:+y) = cos x * cosh y :+ (- sin x * sinh y)
+ tan (x:+y) = (sinx*coshy:+cosx*sinhy)/(cosx*coshy:+(-sinx*sinhy))
+ where sinx = sin x
+ cosx = cos x
+ sinhy = sinh y
+ coshy = cosh y
+
+ sinh (x:+y) = cos y * sinh x :+ sin y * cosh x
+ cosh (x:+y) = cos y * cosh x :+ sin y * sinh x
+ tanh (x:+y) = (cosy*sinhx:+siny*coshx)/(cosy*coshx:+siny*sinhx)
+ where siny = sin y
+ cosy = cos y
+ sinhx = sinh x
+ coshx = cosh x
+
+ asin z@(x:+y) = y':+(-x')
+ where (x':+y') = log (((-y):+x) + sqrt (1 - z*z))
+ acos z = y'':+(-x'')
+ where (x'':+y'') = log (z + ((-y'):+x'))
+ (x':+y') = sqrt (1 - z*z)
+ atan z@(x:+y) = y':+(-x')
+ where (x':+y') = log (((1-y):+x) / sqrt (1+z*z))
+
+ asinh z = log (z + sqrt (1+z*z))
+ acosh z = log (z + (z+1) * sqrt ((z-1)/(z+1)))
+ atanh z = log ((1+z) / sqrt (1-z*z))
diff --git a/libraries/base/Data/Dynamic.hs b/libraries/base/Data/Dynamic.hs
new file mode 100644
index 0000000000..42313fd07c
--- /dev/null
+++ b/libraries/base/Data/Dynamic.hs
@@ -0,0 +1,288 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Dynamic
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Dynamic.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Dynamic interface provides basic support for dynamic types.
+--
+-- Operations for injecting values of arbitrary type into
+-- a dynamically typed value, Dynamic, are provided, together
+-- with operations for converting dynamic values into a concrete
+-- (monomorphic) type.
+--
+-- The Dynamic implementation provided is closely based on code
+-- contained in Hugs library of the same name.
+--
+-----------------------------------------------------------------------------
+
+module Data.Dynamic
+ (
+ -- dynamic type
+ Dynamic -- abstract, instance of: Show, Typeable
+ , toDyn -- :: Typeable a => a -> Dynamic
+ , fromDyn -- :: Typeable a => Dynamic -> a -> a
+ , fromDynamic -- :: Typeable a => Dynamic -> Maybe a
+
+ -- type representation
+
+ , Typeable(
+ typeOf) -- :: a -> TypeRep
+
+ -- Dynamic defines Typeable instances for the following
+ -- Prelude types: [a], (), (a,b), (a,b,c), (a,b,c,d),
+ -- (a,b,c,d,e), (a->b), (Array a b), Bool, Char,
+ -- (Complex a), Double, (Either a b), Float, Handle,
+ -- Int, Integer, (IO a), (Maybe a), Ordering
+
+ , TypeRep -- abstract, instance of: Eq, Show, Typeable
+ , TyCon -- abstract, instance of: Eq, Show, Typeable
+
+ -- type representation constructors/operators:
+ , mkTyCon -- :: String -> TyCon
+ , mkAppTy -- :: TyCon -> [TypeRep] -> TypeRep
+ , mkFunTy -- :: TypeRep -> TypeRep -> TypeRep
+ , applyTy -- :: TypeRep -> TypeRep -> Maybe TypeRep
+
+ --
+ -- let fTy = mkTyCon "Foo" in show (mkAppTy (mkTyCon ",,")
+ -- [fTy,fTy,fTy])
+ --
+ -- returns "(Foo,Foo,Foo)"
+ --
+ -- The TypeRep Show instance promises to print tuple types
+ -- correctly. Tuple type constructors are specified by a
+ -- sequence of commas, e.g., (mkTyCon ",,,,") returns
+ -- the 5-tuple tycon.
+ ) where
+
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.Maybe
+import GHC.Show
+import GHC.Err
+import GHC.Num
+import GHC.Float
+import GHC.IOBase
+import GHC.Dynamic
+#endif
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Prim ( unsafeCoerce# )
+
+unsafeCoerce :: a -> b
+unsafeCoerce = unsafeCoerce#
+#endif
+
+#include "Dynamic.h"
+
+-- The dynamic type is represented by Dynamic, carrying
+-- the dynamic value along with its type representation:
+
+-- the instance just prints the type representation.
+instance Show Dynamic where
+ showsPrec _ (Dynamic t _) =
+ showString "<<" .
+ showsPrec 0 t .
+ showString ">>"
+
+-- Operations for going to and from Dynamic:
+
+toDyn :: Typeable a => a -> Dynamic
+toDyn v = Dynamic (typeOf v) (unsafeCoerce v)
+
+fromDyn :: Typeable a => Dynamic -> a -> a
+fromDyn (Dynamic t v) def
+ | typeOf def == t = unsafeCoerce v
+ | otherwise = def
+
+fromDynamic :: Typeable a => Dynamic -> Maybe a
+fromDynamic (Dynamic t v) =
+ case unsafeCoerce v of
+ r | t == typeOf r -> Just r
+ | otherwise -> Nothing
+
+-- (Abstract) universal datatype:
+
+instance Show TypeRep where
+ showsPrec p (App tycon tys) =
+ case tys of
+ [] -> showsPrec p tycon
+ [x] | tycon == listTc -> showChar '[' . shows x . showChar ']'
+ xs
+ | isTupleTyCon tycon -> showTuple tycon xs
+ | otherwise ->
+ showParen (p > 9) $
+ showsPrec p tycon .
+ showChar ' ' .
+ showArgs tys
+
+ showsPrec p (Fun f a) =
+ showParen (p > 8) $
+ showsPrec 9 f . showString " -> " . showsPrec 8 a
+
+-- To make it possible to convert values with user-defined types
+-- into type Dynamic, we need a systematic way of getting
+-- the type representation of an arbitrary type. A type
+-- class provides just the ticket,
+
+class Typeable a where
+ typeOf :: a -> TypeRep
+
+-- NOTE: The argument to the overloaded `typeOf' is only
+-- used to carry type information, and Typeable instances
+-- should *never* *ever* look at its value.
+
+isTupleTyCon :: TyCon -> Bool
+isTupleTyCon (TyCon _ (',':_)) = True
+isTupleTyCon _ = False
+
+instance Show TyCon where
+ showsPrec _ (TyCon _ s) = showString s
+
+-- If we enforce the restriction that there is only one
+-- @TyCon@ for a type & it is shared among all its uses,
+-- we can map them onto Ints very simply. The benefit is,
+-- of course, that @TyCon@s can then be compared efficiently.
+
+-- Provided the implementor of other @Typeable@ instances
+-- takes care of making all the @TyCon@s CAFs (toplevel constants),
+-- this will work.
+
+-- If this constraint does turn out to be a sore thumb, changing
+-- the Eq instance for TyCons is trivial.
+
+mkTyCon :: String -> TyCon
+mkTyCon str = unsafePerformIO $ do
+ v <- readIORef uni
+ writeIORef uni (v+1)
+ return (TyCon v str)
+
+{-# NOINLINE uni #-}
+uni :: IORef Int
+uni = unsafePerformIO ( newIORef 0 )
+
+-- Some (Show.TypeRep) helpers:
+
+showArgs :: Show a => [a] -> ShowS
+showArgs [] = id
+showArgs [a] = showsPrec 10 a
+showArgs (a:as) = showsPrec 10 a . showString " " . showArgs as
+
+showTuple :: TyCon -> [TypeRep] -> ShowS
+showTuple (TyCon _ str) args = showChar '(' . go str args
+ where
+ go [] [a] = showsPrec 10 a . showChar ')'
+ go _ [] = showChar ')' -- a failure condition, really.
+ go (',':xs) (a:as) = showsPrec 10 a . showChar ',' . go xs as
+ go _ _ = showChar ')'
+
+
+mkAppTy :: TyCon -> [TypeRep] -> TypeRep
+mkAppTy tyc args = App tyc args
+
+mkFunTy :: TypeRep -> TypeRep -> TypeRep
+mkFunTy f a = Fun f a
+
+-- Auxillary functions
+
+-- (f::(a->b)) `dynApply` (x::a) = (f a)::b
+dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
+dynApply (Dynamic t1 f) (Dynamic t2 x) =
+ case applyTy t1 t2 of
+ Just t3 -> Just (Dynamic t3 ((unsafeCoerce f) x))
+ Nothing -> Nothing
+
+dynApp :: Dynamic -> Dynamic -> Dynamic
+dynApp f x = case dynApply f x of
+ Just r -> r
+ Nothing -> error ("Type error in dynamic application.\n" ++
+ "Can't apply function " ++ show f ++
+ " to argument " ++ show x)
+
+applyTy :: TypeRep -> TypeRep -> Maybe TypeRep
+applyTy (Fun t1 t2) t3
+ | t1 == t3 = Just t2
+applyTy _ _ = Nothing
+
+-- Prelude types
+
+listTc :: TyCon
+listTc = mkTyCon "[]"
+
+instance Typeable a => Typeable [a] where
+ typeOf ls = mkAppTy listTc [typeOf ((undefined:: [a] -> a) ls)]
+
+unitTc :: TyCon
+unitTc = mkTyCon "()"
+
+instance Typeable () where
+ typeOf _ = mkAppTy unitTc []
+
+tup2Tc :: TyCon
+tup2Tc = mkTyCon ","
+
+instance (Typeable a, Typeable b) => Typeable (a,b) where
+ typeOf tu = mkAppTy tup2Tc [typeOf ((undefined :: (a,b) -> a) tu),
+ typeOf ((undefined :: (a,b) -> b) tu)]
+
+tup3Tc :: TyCon
+tup3Tc = mkTyCon ",,"
+
+instance ( Typeable a , Typeable b , Typeable c) => Typeable (a,b,c) where
+ typeOf tu = mkAppTy tup3Tc [typeOf ((undefined :: (a,b,c) -> a) tu),
+ typeOf ((undefined :: (a,b,c) -> b) tu),
+ typeOf ((undefined :: (a,b,c) -> c) tu)]
+
+tup4Tc :: TyCon
+tup4Tc = mkTyCon ",,,"
+
+instance ( Typeable a
+ , Typeable b
+ , Typeable c
+ , Typeable d) => Typeable (a,b,c,d) where
+ typeOf tu = mkAppTy tup4Tc [typeOf ((undefined :: (a,b,c,d) -> a) tu),
+ typeOf ((undefined :: (a,b,c,d) -> b) tu),
+ typeOf ((undefined :: (a,b,c,d) -> c) tu),
+ typeOf ((undefined :: (a,b,c,d) -> d) tu)]
+
+tup5Tc :: TyCon
+tup5Tc = mkTyCon ",,,,"
+
+instance ( Typeable a
+ , Typeable b
+ , Typeable c
+ , Typeable d
+ , Typeable e) => Typeable (a,b,c,d,e) where
+ typeOf tu = mkAppTy tup5Tc [typeOf ((undefined :: (a,b,c,d,e) -> a) tu),
+ typeOf ((undefined :: (a,b,c,d,e) -> b) tu),
+ typeOf ((undefined :: (a,b,c,d,e) -> c) tu),
+ typeOf ((undefined :: (a,b,c,d,e) -> d) tu),
+ typeOf ((undefined :: (a,b,c,d,e) -> e) tu)]
+
+instance (Typeable a, Typeable b) => Typeable (a -> b) where
+ typeOf f = mkFunTy (typeOf ((undefined :: (a -> b) -> a) f))
+ (typeOf ((undefined :: (a -> b) -> b) f))
+
+INSTANCE_TYPEABLE0(Bool,boolTc,"Bool")
+INSTANCE_TYPEABLE0(Char,charTc,"Char")
+INSTANCE_TYPEABLE0(Float,floatTc,"Float")
+INSTANCE_TYPEABLE0(Double,doubleTc,"Double")
+INSTANCE_TYPEABLE0(Int,intTc,"Int")
+INSTANCE_TYPEABLE0(Integer,integerTc,"Integer")
+INSTANCE_TYPEABLE2(Either,eitherTc,"Either")
+INSTANCE_TYPEABLE1(IO,ioTc,"IO")
+INSTANCE_TYPEABLE1(Maybe,maybeTc,"Maybe")
+INSTANCE_TYPEABLE0(Ordering,orderingTc,"Ordering")
+
+INSTANCE_TYPEABLE0(TyCon,tyconTc,"TyCon")
+INSTANCE_TYPEABLE0(TypeRep,typeRepTc,"TypeRep")
+INSTANCE_TYPEABLE0(Dynamic,dynamicTc,"Dynamic")
diff --git a/libraries/base/Data/Either.hs b/libraries/base/Data/Either.hs
new file mode 100644
index 0000000000..f3cd106655
--- /dev/null
+++ b/libraries/base/Data/Either.hs
@@ -0,0 +1,25 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Either
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Either.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Either type, and associated operations.
+--
+-----------------------------------------------------------------------------
+
+module Data.Either (
+ Either(..),
+ either -- :: (a -> c) -> (b -> c) -> Either a b -> c
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Maybe
+#endif
diff --git a/libraries/base/Data/IORef.hs b/libraries/base/Data/IORef.hs
new file mode 100644
index 0000000000..f0738277dd
--- /dev/null
+++ b/libraries/base/Data/IORef.hs
@@ -0,0 +1,57 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.IORef
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: IORef.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Mutable references in the IO monad.
+--
+-----------------------------------------------------------------------------
+
+module Data.IORef
+ ( IORef -- abstract, instance of: Eq, Typeable
+ , newIORef -- :: a -> IO (IORef a)
+ , readIORef -- :: IORef a -> IO a
+ , writeIORef -- :: IORef a -> a -> IO ()
+ , modifyIORef -- :: IORef a -> (a -> a) -> IO ()
+
+#if !defined(__PARALLEL_HASKELL__) && defined(__GLASGOW_HASKELL__)
+ , mkWeakIORef -- :: IORef a -> IO () -> IO (Weak (IORef a))
+#endif
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Prim ( mkWeak# )
+import GHC.STRef
+import GHC.IOBase
+#if !defined(__PARALLEL_HASKELL__)
+import GHC.Weak
+#endif
+#endif /* __GLASGOW_HASKELL__ */
+
+#ifdef __HUGS__
+import IOExts ( IORef, newIORef, writeIORef, readIORef )
+import ST ( stToIO, newSTRef, readSTRef, writeSTRef )
+#endif
+
+import Data.Dynamic
+
+#ifndef __PARALLEL_HASKELL__
+mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a))
+mkWeakIORef r@(IORef (STRef r#)) f = IO $ \s ->
+ case mkWeak# r# r f s of (# s1, w #) -> (# s1, Weak w #)
+#endif
+
+modifyIORef :: IORef a -> (a -> a) -> IO ()
+modifyIORef ref f = writeIORef ref . f =<< readIORef ref
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE1(IORef,ioRefTc,"IORef")
diff --git a/libraries/base/Data/Int.hs b/libraries/base/Data/Int.hs
new file mode 100644
index 0000000000..3a1042a433
--- /dev/null
+++ b/libraries/base/Data/Int.hs
@@ -0,0 +1,37 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Int
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Int.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Sized Integer types.
+--
+-----------------------------------------------------------------------------
+
+module Data.Int
+ ( Int8
+ , Int16
+ , Int32
+ , Int64
+ -- instances: Eq, Ord, Num, Bounded, Real, Integral, Ix, Enum, Read,
+ -- Show, Bits, CCallable, CReturnable (last two are GHC specific.)
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Int
+#endif
+
+import Data.Dynamic
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(Int8,int8Tc, "Int8")
+INSTANCE_TYPEABLE0(Int16,int16Tc,"Int16")
+INSTANCE_TYPEABLE0(Int32,int32Tc,"Int32")
+INSTANCE_TYPEABLE0(Int64,int64Tc,"Int64")
diff --git a/libraries/base/Data/Ix.hs b/libraries/base/Data/Ix.hs
new file mode 100644
index 0000000000..8d4d7452e2
--- /dev/null
+++ b/libraries/base/Data/Ix.hs
@@ -0,0 +1,43 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Ix
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Ix.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Class of index types.
+--
+-----------------------------------------------------------------------------
+
+module Data.Ix
+ (
+ Ix
+ ( range -- :: (Ix a) => (a,a) -> [a]
+ , index -- :: (Ix a) => (a,a) -> a -> Int
+ , inRange -- :: (Ix a) => (a,a) -> a -> Bool
+ )
+ , rangeSize -- :: (Ix a) => (a,a) -> Int
+ -- Ix instances:
+ --
+ -- Ix Char
+ -- Ix Int
+ -- Ix Integer
+ -- Ix Bool
+ -- Ix Ordering
+ -- Ix ()
+ -- (Ix a, Ix b) => Ix (a, b)
+ -- ...
+
+ -- Implementation checked wrt. Haskell 98 lib report, 1/99.
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Arr
+#endif
diff --git a/libraries/base/Data/List.hs b/libraries/base/Data/List.hs
new file mode 100644
index 0000000000..ce4c9b32f2
--- /dev/null
+++ b/libraries/base/Data/List.hs
@@ -0,0 +1,537 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.List
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: List.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Operations on lists.
+--
+-----------------------------------------------------------------------------
+
+module Data.List
+ (
+ [] (..),
+
+ , elemIndex -- :: (Eq a) => a -> [a] -> Maybe Int
+ , elemIndices -- :: (Eq a) => a -> [a] -> [Int]
+
+ , find -- :: (a -> Bool) -> [a] -> Maybe a
+ , findIndex -- :: (a -> Bool) -> [a] -> Maybe Int
+ , findIndices -- :: (a -> Bool) -> [a] -> [Int]
+
+ , nub -- :: (Eq a) => [a] -> [a]
+ , nubBy -- :: (a -> a -> Bool) -> [a] -> [a]
+
+ , delete -- :: (Eq a) => a -> [a] -> [a]
+ , deleteBy -- :: (a -> a -> Bool) -> a -> [a] -> [a]
+ , (\\) -- :: (Eq a) => [a] -> [a] -> [a]
+ , deleteFirstsBy -- :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+
+ , union -- :: (Eq a) => [a] -> [a] -> [a]
+ , unionBy -- :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+
+ , intersect -- :: (Eq a) => [a] -> [a] -> [a]
+ , intersectBy -- :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+
+ , intersperse -- :: a -> [a] -> [a]
+ , transpose -- :: [[a]] -> [[a]]
+ , partition -- :: (a -> Bool) -> [a] -> ([a], [a])
+
+ , group -- :: Eq a => [a] -> [[a]]
+ , groupBy -- :: (a -> a -> Bool) -> [a] -> [[a]]
+
+ , inits -- :: [a] -> [[a]]
+ , tails -- :: [a] -> [[a]]
+
+ , isPrefixOf -- :: (Eq a) => [a] -> [a] -> Bool
+ , isSuffixOf -- :: (Eq a) => [a] -> [a] -> Bool
+
+ , mapAccumL -- :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])
+ , mapAccumR -- :: (a -> b -> (a,c)) -> a -> [b] -> (a,[c])
+
+ , sort -- :: (Ord a) => [a] -> [a]
+ , sortBy -- :: (a -> a -> Ordering) -> [a] -> [a]
+
+ , insert -- :: (Ord a) => a -> [a] -> [a]
+ , insertBy -- :: (a -> a -> Ordering) -> a -> [a] -> [a]
+
+ , maximumBy -- :: (a -> a -> Ordering) -> [a] -> a
+ , minimumBy -- :: (a -> a -> Ordering) -> [a] -> a
+
+ , genericLength -- :: (Integral a) => [b] -> a
+ , genericTake -- :: (Integral a) => a -> [b] -> [b]
+ , genericDrop -- :: (Integral a) => a -> [b] -> [b]
+ , genericSplitAt -- :: (Integral a) => a -> [b] -> ([b], [b])
+ , genericIndex -- :: (Integral a) => [b] -> a -> b
+ , genericReplicate -- :: (Integral a) => a -> b -> [b]
+
+ , unfoldr -- :: (b -> Maybe (a, b)) -> b -> [a]
+
+ , zip4, zip5, zip6, zip7
+ , zipWith4, zipWith5, zipWith6, zipWith7
+ , unzip4, unzip5, unzip6, unzip7
+
+ , map -- :: ( a -> b ) -> [a] -> [b]
+ , (++) -- :: [a] -> [a] -> [a]
+ , concat -- :: [[a]] -> [a]
+ , filter -- :: (a -> Bool) -> [a] -> [a]
+ , head -- :: [a] -> a
+ , last -- :: [a] -> a
+ , tail -- :: [a] -> [a]
+ , init -- :: [a] -> [a]
+ , null -- :: [a] -> Bool
+ , length -- :: [a] -> Int
+ , (!!) -- :: [a] -> Int -> a
+ , foldl -- :: (a -> b -> a) -> a -> [b] -> a
+ , foldl1 -- :: (a -> a -> a) -> [a] -> a
+ , scanl -- :: (a -> b -> a) -> a -> [b] -> [a]
+ , scanl1 -- :: (a -> a -> a) -> [a] -> [a]
+ , foldr -- :: (a -> b -> b) -> b -> [a] -> b
+ , foldr1 -- :: (a -> a -> a) -> [a] -> a
+ , scanr -- :: (a -> b -> b) -> b -> [a] -> [b]
+ , scanr1 -- :: (a -> a -> a) -> [a] -> [a]
+ , iterate -- :: (a -> a) -> a -> [a]
+ , repeat -- :: a -> [a]
+ , replicate -- :: Int -> a -> [a]
+ , cycle -- :: [a] -> [a]
+ , take -- :: Int -> [a] -> [a]
+ , drop -- :: Int -> [a] -> [a]
+ , splitAt -- :: Int -> [a] -> ([a], [a])
+ , takeWhile -- :: (a -> Bool) -> [a] -> [a]
+ , dropWhile -- :: (a -> Bool) -> [a] -> [a]
+ , span -- :: (a -> Bool) -> [a] -> ([a], [a])
+ , break -- :: (a -> Bool) -> [a] -> ([a], [a])
+
+ , lines -- :: String -> [String]
+ , words -- :: String -> [String]
+ , unlines -- :: [String] -> String
+ , unwords -- :: [String] -> String
+ , reverse -- :: [a] -> [a]
+ , and -- :: [Bool] -> Bool
+ , or -- :: [Bool] -> Bool
+ , any -- :: (a -> Bool) -> [a] -> Bool
+ , all -- :: (a -> Bool) -> [a] -> Bool
+ , elem -- :: a -> [a] -> Bool
+ , notElem -- :: a -> [a] -> Bool
+ , lookup -- :: (Eq a) => a -> [(a,b)] -> Maybe b
+ , sum -- :: (Num a) => [a] -> a
+ , product -- :: (Num a) => [a] -> a
+ , maximum -- :: (Ord a) => [a] -> a
+ , minimum -- :: (Ord a) => [a] -> a
+ , concatMap -- :: (a -> [b]) -> [a] -> [b]
+ , zip -- :: [a] -> [b] -> [(a,b)]
+ , zip3
+ , zipWith -- :: (a -> b -> c) -> [a] -> [b] -> [c]
+ , zipWith3
+ , unzip -- :: [(a,b)] -> ([a],[b])
+ , unzip3
+
+ ) where
+
+import Data.Maybe
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Num
+import GHC.Real
+import GHC.List
+import GHC.Show ( lines, words, unlines, unwords )
+import GHC.Base
+#endif
+
+infix 5 \\
+
+-- -----------------------------------------------------------------------------
+-- List functions
+
+elemIndex :: Eq a => a -> [a] -> Maybe Int
+elemIndex x = findIndex (x==)
+
+elemIndices :: Eq a => a -> [a] -> [Int]
+elemIndices x = findIndices (x==)
+
+find :: (a -> Bool) -> [a] -> Maybe a
+find p = listToMaybe . filter p
+
+findIndex :: (a -> Bool) -> [a] -> Maybe Int
+findIndex p = listToMaybe . findIndices p
+
+findIndices :: (a -> Bool) -> [a] -> [Int]
+
+#ifdef USE_REPORT_PRELUDE
+findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]
+#else
+#ifdef __HUGS__
+findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]
+#else
+-- Efficient definition
+findIndices p ls = loop 0# ls
+ where
+ loop _ [] = []
+ loop n (x:xs) | p x = I# n : loop (n +# 1#) xs
+ | otherwise = loop (n +# 1#) xs
+#endif /* __HUGS__ */
+#endif /* USE_REPORT_PRELUDE */
+
+isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
+isPrefixOf [] _ = True
+isPrefixOf _ [] = False
+isPrefixOf (x:xs) (y:ys)= x == y && isPrefixOf xs ys
+
+isSuffixOf :: (Eq a) => [a] -> [a] -> Bool
+isSuffixOf x y = reverse x `isPrefixOf` reverse y
+
+-- nub (meaning "essence") remove duplicate elements from its list argument.
+nub :: (Eq a) => [a] -> [a]
+#ifdef USE_REPORT_PRELUDE
+nub = nubBy (==)
+#else
+-- stolen from HBC
+nub l = nub' l [] -- '
+ where
+ nub' [] _ = [] -- '
+ nub' (x:xs) ls -- '
+ | x `elem` ls = nub' xs ls -- '
+ | otherwise = x : nub' xs (x:ls) -- '
+#endif
+
+nubBy :: (a -> a -> Bool) -> [a] -> [a]
+#ifdef USE_REPORT_PRELUDE
+nubBy eq [] = []
+nubBy eq (x:xs) = x : nubBy eq (filter (\ y -> not (eq x y)) xs)
+#else
+nubBy eq l = nubBy' l []
+ where
+ nubBy' [] _ = []
+ nubBy' (y:ys) xs
+ | elem_by eq y xs = nubBy' ys xs
+ | otherwise = y : nubBy' ys (y:xs)
+
+-- Not exported:
+-- Note that we keep the call to `eq` with arguments in the
+-- same order as in the reference implementation
+-- 'xs' is the list of things we've seen so far,
+-- 'y' is the potential new element
+elem_by :: (a -> a -> Bool) -> a -> [a] -> Bool
+elem_by _ _ [] = False
+elem_by eq y (x:xs) = x `eq` y || elem_by eq y xs
+#endif
+
+
+-- delete x removes the first occurrence of x from its list argument.
+delete :: (Eq a) => a -> [a] -> [a]
+delete = deleteBy (==)
+
+deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]
+deleteBy _ _ [] = []
+deleteBy eq x (y:ys) = if x `eq` y then ys else y : deleteBy eq x ys
+
+-- list difference (non-associative). In the result of xs \\ ys,
+-- the first occurrence of each element of ys in turn (if any)
+-- has been removed from xs. Thus, (xs ++ ys) \\ xs == ys.
+(\\) :: (Eq a) => [a] -> [a] -> [a]
+(\\) = foldl (flip delete)
+
+-- List union, remove the elements of first list from second.
+union :: (Eq a) => [a] -> [a] -> [a]
+union = unionBy (==)
+
+unionBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+unionBy eq xs ys = xs ++ foldl (flip (deleteBy eq)) (nubBy eq ys) xs
+
+intersect :: (Eq a) => [a] -> [a] -> [a]
+intersect = intersectBy (==)
+
+intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+intersectBy eq xs ys = [x | x <- xs, any (eq x) ys]
+
+-- intersperse sep inserts sep between the elements of its list argument.
+-- e.g. intersperse ',' "abcde" == "a,b,c,d,e"
+intersperse :: a -> [a] -> [a]
+intersperse _ [] = []
+intersperse _ [x] = [x]
+intersperse sep (x:xs) = x : sep : intersperse sep xs
+
+transpose :: [[a]] -> [[a]]
+transpose [] = []
+transpose ([] : xss) = transpose xss
+transpose ((x:xs) : xss) = (x : [h | (h:t) <- xss]) : transpose (xs : [ t | (h:t) <- xss])
+
+
+-- partition takes a predicate and a list and returns a pair of lists:
+-- those elements of the argument list that do and do not satisfy the
+-- predicate, respectively; i,e,,
+-- partition p xs == (filter p xs, filter (not . p) xs).
+partition :: (a -> Bool) -> [a] -> ([a],[a])
+{-# INLINE partition #-}
+partition p xs = foldr (select p) ([],[]) xs
+
+select p x (ts,fs) | p x = (x:ts,fs)
+ | otherwise = (ts, x:fs)
+
+-- @mapAccumL@ behaves like a combination
+-- of @map@ and @foldl@;
+-- it applies a function to each element of a list, passing an accumulating
+-- parameter from left to right, and returning a final value of this
+-- accumulator together with the new list.
+
+mapAccumL :: (acc -> x -> (acc, y)) -- Function of elt of input list
+ -- and accumulator, returning new
+ -- accumulator and elt of result list
+ -> acc -- Initial accumulator
+ -> [x] -- Input list
+ -> (acc, [y]) -- Final accumulator and result list
+mapAccumL _ s [] = (s, [])
+mapAccumL f s (x:xs) = (s'',y:ys)
+ where (s', y ) = f s x
+ (s'',ys) = mapAccumL f s' xs
+
+-- @mapAccumR@ does the same, but working from right to left instead.
+-- Its type is the same as @mapAccumL@, though.
+
+mapAccumR :: (acc -> x -> (acc, y)) -- Function of elt of input list
+ -- and accumulator, returning new
+ -- accumulator and elt of result list
+ -> acc -- Initial accumulator
+ -> [x] -- Input list
+ -> (acc, [y]) -- Final accumulator and result list
+mapAccumR _ s [] = (s, [])
+mapAccumR f s (x:xs) = (s'', y:ys)
+ where (s'',y ) = f s' x
+ (s', ys) = mapAccumR f s xs
+
+
+insert :: Ord a => a -> [a] -> [a]
+insert e ls = insertBy (compare) e ls
+
+insertBy :: (a -> a -> Ordering) -> a -> [a] -> [a]
+insertBy _ x [] = [x]
+insertBy cmp x ys@(y:ys')
+ = case cmp x y of
+ GT -> y : insertBy cmp x ys'
+ _ -> x : ys
+
+maximumBy :: (a -> a -> a) -> [a] -> a
+maximumBy _ [] = error "List.maximumBy: empty list"
+maximumBy max xs = foldl1 max xs
+
+minimumBy :: (a -> a -> a) -> [a] -> a
+minimumBy _ [] = error "List.minimumBy: empty list"
+minimumBy min xs = foldl1 min xs
+
+genericLength :: (Num i) => [b] -> i
+genericLength [] = 0
+genericLength (_:l) = 1 + genericLength l
+
+genericTake :: (Integral i) => i -> [a] -> [a]
+genericTake 0 _ = []
+genericTake _ [] = []
+genericTake n (x:xs) | n > 0 = x : genericTake (n-1) xs
+genericTake _ _ = error "List.genericTake: negative argument"
+
+genericDrop :: (Integral i) => i -> [a] -> [a]
+genericDrop 0 xs = xs
+genericDrop _ [] = []
+genericDrop n (_:xs) | n > 0 = genericDrop (n-1) xs
+genericDrop _ _ = error "List.genericDrop: negative argument"
+
+genericSplitAt :: (Integral i) => i -> [b] -> ([b],[b])
+genericSplitAt 0 xs = ([],xs)
+genericSplitAt _ [] = ([],[])
+genericSplitAt n (x:xs) | n > 0 = (x:xs',xs'') where
+ (xs',xs'') = genericSplitAt (n-1) xs
+genericSplitAt _ _ = error "List.genericSplitAt: negative argument"
+
+
+genericIndex :: (Integral a) => [b] -> a -> b
+genericIndex (x:_) 0 = x
+genericIndex (_:xs) n
+ | n > 0 = genericIndex xs (n-1)
+ | otherwise = error "List.genericIndex: negative argument."
+genericIndex _ _ = error "List.genericIndex: index too large."
+
+genericReplicate :: (Integral i) => i -> a -> [a]
+genericReplicate n x = genericTake n (repeat x)
+
+
+zip4 :: [a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]
+zip4 = zipWith4 (,,,)
+
+zip5 :: [a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]
+zip5 = zipWith5 (,,,,)
+
+zip6 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] ->
+ [(a,b,c,d,e,f)]
+zip6 = zipWith6 (,,,,,)
+
+zip7 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] ->
+ [g] -> [(a,b,c,d,e,f,g)]
+zip7 = zipWith7 (,,,,,,)
+
+zipWith4 :: (a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]
+zipWith4 z (a:as) (b:bs) (c:cs) (d:ds)
+ = z a b c d : zipWith4 z as bs cs ds
+zipWith4 _ _ _ _ _ = []
+
+zipWith5 :: (a->b->c->d->e->f) ->
+ [a]->[b]->[c]->[d]->[e]->[f]
+zipWith5 z (a:as) (b:bs) (c:cs) (d:ds) (e:es)
+ = z a b c d e : zipWith5 z as bs cs ds es
+zipWith5 _ _ _ _ _ _ = []
+
+zipWith6 :: (a->b->c->d->e->f->g) ->
+ [a]->[b]->[c]->[d]->[e]->[f]->[g]
+zipWith6 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs)
+ = z a b c d e f : zipWith6 z as bs cs ds es fs
+zipWith6 _ _ _ _ _ _ _ = []
+
+zipWith7 :: (a->b->c->d->e->f->g->h) ->
+ [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]
+zipWith7 z (a:as) (b:bs) (c:cs) (d:ds) (e:es) (f:fs) (g:gs)
+ = z a b c d e f g : zipWith7 z as bs cs ds es fs gs
+zipWith7 _ _ _ _ _ _ _ _ = []
+
+unzip4 :: [(a,b,c,d)] -> ([a],[b],[c],[d])
+unzip4 = foldr (\(a,b,c,d) ~(as,bs,cs,ds) ->
+ (a:as,b:bs,c:cs,d:ds))
+ ([],[],[],[])
+
+unzip5 :: [(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])
+unzip5 = foldr (\(a,b,c,d,e) ~(as,bs,cs,ds,es) ->
+ (a:as,b:bs,c:cs,d:ds,e:es))
+ ([],[],[],[],[])
+
+unzip6 :: [(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])
+unzip6 = foldr (\(a,b,c,d,e,f) ~(as,bs,cs,ds,es,fs) ->
+ (a:as,b:bs,c:cs,d:ds,e:es,f:fs))
+ ([],[],[],[],[],[])
+
+unzip7 :: [(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])
+unzip7 = foldr (\(a,b,c,d,e,f,g) ~(as,bs,cs,ds,es,fs,gs) ->
+ (a:as,b:bs,c:cs,d:ds,e:es,f:fs,g:gs))
+ ([],[],[],[],[],[],[])
+
+
+
+deleteFirstsBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
+deleteFirstsBy eq = foldl (flip (deleteBy eq))
+
+
+-- group splits its list argument into a list of lists of equal, adjacent
+-- elements. e.g.,
+-- group "Mississippi" == ["M","i","ss","i","ss","i","pp","i"]
+group :: (Eq a) => [a] -> [[a]]
+group = groupBy (==)
+
+groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
+groupBy _ [] = []
+groupBy eq (x:xs) = (x:ys) : groupBy eq zs
+ where (ys,zs) = span (eq x) xs
+
+-- inits xs returns the list of initial segments of xs, shortest first.
+-- e.g., inits "abc" == ["","a","ab","abc"]
+inits :: [a] -> [[a]]
+inits [] = [[]]
+inits (x:xs) = [[]] ++ map (x:) (inits xs)
+
+-- tails xs returns the list of all final segments of xs, longest first.
+-- e.g., tails "abc" == ["abc", "bc", "c",""]
+tails :: [a] -> [[a]]
+tails [] = [[]]
+tails xxs@(_:xs) = xxs : tails xs
+
+
+------------------------------------------------------------------------------
+-- Quick Sort algorithm taken from HBC's QSort library.
+
+sort :: (Ord a) => [a] -> [a]
+sortBy :: (a -> a -> Ordering) -> [a] -> [a]
+
+#ifdef USE_REPORT_PRELUDE
+sort = sortBy compare
+sortBy cmp = foldr (insertBy cmp) []
+#else
+
+sortBy cmp l = qsort cmp l []
+sort l = qsort compare l []
+
+-- rest is not exported:
+
+-- qsort is stable and does not concatenate.
+qsort :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
+qsort _ [] r = r
+qsort _ [x] r = x:r
+qsort cmp (x:xs) r = qpart cmp x xs [] [] r
+
+-- qpart partitions and sorts the sublists
+qpart :: (a -> a -> Ordering) -> a -> [a] -> [a] -> [a] -> [a] -> [a]
+qpart cmp x [] rlt rge r =
+ -- rlt and rge are in reverse order and must be sorted with an
+ -- anti-stable sorting
+ rqsort cmp rlt (x:rqsort cmp rge r)
+qpart cmp x (y:ys) rlt rge r =
+ case cmp x y of
+ GT -> qpart cmp x ys (y:rlt) rge r
+ _ -> qpart cmp x ys rlt (y:rge) r
+
+-- rqsort is as qsort but anti-stable, i.e. reverses equal elements
+rqsort :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
+rqsort _ [] r = r
+rqsort _ [x] r = x:r
+rqsort cmp (x:xs) r = rqpart cmp x xs [] [] r
+
+rqpart :: (a -> a -> Ordering) -> a -> [a] -> [a] -> [a] -> [a] -> [a]
+rqpart cmp x [] rle rgt r =
+ qsort cmp rle (x:qsort cmp rgt r)
+rqpart cmp x (y:ys) rle rgt r =
+ case cmp y x of
+ GT -> rqpart cmp x ys rle (y:rgt) r
+ _ -> rqpart cmp x ys (y:rle) rgt r
+
+#endif /* USE_REPORT_PRELUDE */
+
+{-
+\begin{verbatim}
+ unfoldr f' (foldr f z xs) == (z,xs)
+
+ if the following holds:
+
+ f' (f x y) = Just (x,y)
+ f' z = Nothing
+\end{verbatim}
+-}
+
+unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
+unfoldr f b =
+ case f b of
+ Just (a,new_b) -> a : unfoldr f new_b
+ Nothing -> []
+
+-- -----------------------------------------------------------------------------
+-- List sum and product
+
+-- sum and product compute the sum or product of a finite list of numbers.
+{-# SPECIALISE sum :: [Int] -> Int #-}
+{-# SPECIALISE sum :: [Integer] -> Integer #-}
+{-# SPECIALISE product :: [Int] -> Int #-}
+{-# SPECIALISE product :: [Integer] -> Integer #-}
+sum, product :: (Num a) => [a] -> a
+#ifdef USE_REPORT_PRELUDE
+sum = foldl (+) 0
+product = foldl (*) 1
+#else
+sum l = sum' l 0
+ where
+ sum' [] a = a
+ sum' (x:xs) a = sum' xs (a+x)
+product l = prod l 1
+ where
+ prod [] a = a
+ prod (x:xs) a = prod xs (a*x)
+#endif
diff --git a/libraries/base/Data/Maybe.hs b/libraries/base/Data/Maybe.hs
new file mode 100644
index 0000000000..06c7a25398
--- /dev/null
+++ b/libraries/base/Data/Maybe.hs
@@ -0,0 +1,75 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Maybe
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Maybe.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The Maybe type, and associated operations.
+--
+-----------------------------------------------------------------------------
+
+module Data.Maybe
+ (
+ Maybe(Nothing,Just)-- instance of: Eq, Ord, Show, Read,
+ -- Functor, Monad, MonadPlus
+
+ , maybe -- :: b -> (a -> b) -> Maybe a -> b
+
+ , isJust -- :: Maybe a -> Bool
+ , isNothing -- :: Maybe a -> Bool
+ , fromJust -- :: Maybe a -> a
+ , fromMaybe -- :: a -> Maybe a -> a
+ , listToMaybe -- :: [a] -> Maybe a
+ , maybeToList -- :: Maybe a -> [a]
+ , catMaybes -- :: [Maybe a] -> [a]
+ , mapMaybe -- :: (a -> Maybe b) -> [a] -> [b]
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Err ( error )
+import GHC.List
+import GHC.Maybe
+import GHC.Base
+#endif
+
+isJust :: Maybe a -> Bool
+isJust Nothing = False
+isJust _ = True
+
+isNothing :: Maybe a -> Bool
+isNothing Nothing = True
+isNothing _ = False
+
+fromJust :: Maybe a -> a
+fromJust Nothing = error "Maybe.fromJust: Nothing" -- yuck
+fromJust (Just x) = x
+
+fromMaybe :: a -> Maybe a -> a
+fromMaybe d x = case x of {Nothing -> d;Just v -> v}
+
+maybeToList :: Maybe a -> [a]
+maybeToList Nothing = []
+maybeToList (Just x) = [x]
+
+listToMaybe :: [a] -> Maybe a
+listToMaybe [] = Nothing
+listToMaybe (a:_) = Just a
+
+catMaybes :: [Maybe a] -> [a]
+catMaybes ls = [x | Just x <- ls]
+
+mapMaybe :: (a -> Maybe b) -> [a] -> [b]
+mapMaybe _ [] = []
+mapMaybe f (x:xs) =
+ let rs = mapMaybe f xs in
+ case f x of
+ Nothing -> rs
+ Just r -> r:rs
+
diff --git a/libraries/base/Data/PackedString.hs b/libraries/base/Data/PackedString.hs
new file mode 100644
index 0000000000..6fc1a8f2be
--- /dev/null
+++ b/libraries/base/Data/PackedString.hs
@@ -0,0 +1,914 @@
+{-# OPTIONS -#include "PackedString.h" #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Data.PackedString
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: PackedString.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The PackedString type, and associated operations.
+-- GHC implementation by Bryan O'Sullivan.
+--
+-----------------------------------------------------------------------------
+
+module Data.PackedString (
+ PackedString, -- abstract, instances: Eq, Ord, Show, Typeable
+
+ -- Creating the beasts
+ packString, -- :: [Char] -> PackedString
+ packStringST, -- :: [Char] -> ST s PackedString
+ packCBytesST, -- :: Int -> Ptr a -> ST s PackedString
+
+ byteArrayToPS, -- :: ByteArray Int -> PackedString
+ cByteArrayToPS, -- :: ByteArray Int -> PackedString
+ unsafeByteArrayToPS, -- :: ByteArray a -> Int -> PackedString
+
+ psToByteArray, -- :: PackedString -> ByteArray Int
+ psToCString, -- :: PackedString -> Ptr a
+ isCString, -- :: PackedString -> Bool
+
+ unpackPS, -- :: PackedString -> [Char]
+ unpackNBytesPS, -- :: PackedString -> Int -> [Char]
+ unpackPSIO, -- :: PackedString -> IO [Char]
+
+ hPutPS, -- :: Handle -> PackedString -> IO ()
+ hGetPS, -- :: Handle -> Int -> IO PackedString
+
+ nilPS, -- :: PackedString
+ consPS, -- :: Char -> PackedString -> PackedString
+ headPS, -- :: PackedString -> Char
+ tailPS, -- :: PackedString -> PackedString
+ nullPS, -- :: PackedString -> Bool
+ appendPS, -- :: PackedString -> PackedString -> PackedString
+ lengthPS, -- :: PackedString -> Int
+ {- 0-origin indexing into the string -}
+ indexPS, -- :: PackedString -> Int -> Char
+ mapPS, -- :: (Char -> Char) -> PackedString -> PackedString
+ filterPS, -- :: (Char -> Bool) -> PackedString -> PackedString
+ foldlPS, -- :: (a -> Char -> a) -> a -> PackedString -> a
+ foldrPS, -- :: (Char -> a -> a) -> a -> PackedString -> a
+ takePS, -- :: Int -> PackedString -> PackedString
+ dropPS, -- :: Int -> PackedString -> PackedString
+ splitAtPS, -- :: Int -> PackedString -> (PackedString, PackedString)
+ takeWhilePS, -- :: (Char -> Bool) -> PackedString -> PackedString
+ dropWhilePS, -- :: (Char -> Bool) -> PackedString -> PackedString
+ spanPS, -- :: (Char -> Bool) -> PackedString -> (PackedString, PackedString)
+ breakPS, -- :: (Char -> Bool) -> PackedString -> (PackedString, PackedString)
+ linesPS, -- :: PackedString -> [PackedString]
+
+ wordsPS, -- :: PackedString -> [PackedString]
+ reversePS, -- :: PackedString -> PackedString
+ splitPS, -- :: Char -> PackedString -> [PackedString]
+ splitWithPS, -- :: (Char -> Bool) -> PackedString -> [PackedString]
+ joinPS, -- :: PackedString -> [PackedString] -> PackedString
+ concatPS, -- :: [PackedString] -> PackedString
+ elemPS, -- :: Char -> PackedString -> Bool
+
+ {-
+ Pluck out a piece of a PS start and end
+ chars you want; both 0-origin-specified
+ -}
+ substrPS, -- :: PackedString -> Int -> Int -> PackedString
+
+ comparePS -- :: PackedString -> PackedString -> Ordering
+
+ ) where
+
+import Prelude
+
+import Foreign
+import Foreign.C
+
+import GHC.Prim
+import GHC.Base
+import GHC.ST
+import GHC.ByteArr
+
+import GHC.Show ( showList__ ) -- ToDo: better
+import GHC.Pack ( new_ps_array, freeze_ps_array, write_ps_array )
+
+import Control.Monad.ST
+
+import System.IO
+import System.IO.Unsafe ( unsafePerformIO )
+import GHC.IO ( hPutBufBA, hGetBufBA )
+
+import Data.Ix
+import Data.Char ( isSpace )
+import Data.Dynamic
+
+-- -----------------------------------------------------------------------------
+-- PackedString type declaration
+
+data PackedString
+ = PS ByteArray# -- the bytes
+ Int# -- length (*not* including NUL at the end)
+ Bool -- True <=> contains a NUL
+ | CPS Addr# -- pointer to the (null-terminated) bytes in C land
+ Int# -- length, as per strlen
+ -- definitely doesn't contain a NUL
+
+instance Eq PackedString where
+ x == y = compare x y == EQ
+ x /= y = compare x y /= EQ
+
+instance Ord PackedString where
+ compare = comparePS
+ x <= y = compare x y /= GT
+ x < y = compare x y == LT
+ x >= y = compare x y /= LT
+ x > y = compare x y == GT
+ max x y = case (compare x y) of { LT -> y ; EQ -> x ; GT -> x }
+ min x y = case (compare x y) of { LT -> x ; EQ -> x ; GT -> y }
+
+--instance Read PackedString: ToDo
+
+instance Show PackedString where
+ showsPrec p ps r = showsPrec p (unpackPS ps) r
+ showList = showList__ (showsPrec 0)
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(PackedString,packedStringTc,"PackedString")
+
+-- -----------------------------------------------------------------------------
+-- PackedString instances
+
+-- We try hard to make this go fast:
+
+comparePS :: PackedString -> PackedString -> Ordering
+
+comparePS (PS bs1 len1 has_null1) (PS bs2 len2 has_null2)
+ | not has_null1 && not has_null2
+ = unsafePerformIO (
+ _ccall_ strcmp ba1 ba2 >>= \ (I# res) ->
+ return (
+ if res <# 0# then LT
+ else if res ==# 0# then EQ
+ else GT
+ ))
+ where
+ ba1 = ByteArray 0 (I# (len1 -# 1#)) bs1
+ ba2 = ByteArray 0 (I# (len2 -# 1#)) bs2
+
+comparePS (PS bs1 len1 has_null1) (CPS bs2 _)
+ | not has_null1
+ = unsafePerformIO (
+ _ccall_ strcmp ba1 ba2 >>= \ (I# res) ->
+ return (
+ if res <# 0# then LT
+ else if res ==# 0# then EQ
+ else GT
+ ))
+ where
+ ba1 = ByteArray 0 (I# (len1 -# 1#)) bs1
+ ba2 = Ptr bs2
+
+comparePS (CPS bs1 len1) (CPS bs2 _)
+ = unsafePerformIO (
+ _ccall_ strcmp ba1 ba2 >>= \ (I# res) ->
+ return (
+ if res <# 0# then LT
+ else if res ==# 0# then EQ
+ else GT
+ ))
+ where
+ ba1 = Ptr bs1
+ ba2 = Ptr bs2
+
+comparePS a@(CPS _ _) b@(PS _ _ has_null2)
+ | not has_null2
+ = -- try them the other way 'round
+ case (comparePS b a) of { LT -> GT; EQ -> EQ; GT -> LT }
+
+comparePS ps1 ps2 -- slow catch-all case (esp for "has_null" True)
+ = looking_at 0#
+ where
+ end1 = lengthPS# ps1 -# 1#
+ end2 = lengthPS# ps2 -# 1#
+
+ looking_at char#
+ = if char# ># end1 then
+ if char# ># end2 then -- both strings ran out at once
+ EQ
+ else -- ps1 ran out before ps2
+ LT
+ else if char# ># end2 then
+ GT -- ps2 ran out before ps1
+ else
+ let
+ ch1 = indexPS# ps1 char#
+ ch2 = indexPS# ps2 char#
+ in
+ if ch1 `eqChar#` ch2 then
+ looking_at (char# +# 1#)
+ else if ch1 `ltChar#` ch2 then LT
+ else GT
+
+
+-- -----------------------------------------------------------------------------
+-- Constructor functions
+
+-- Easy ones first. @packString@ requires getting some heap-bytes and
+-- scribbling stuff into them.
+
+nilPS :: PackedString
+nilPS = CPS ""# 0#
+
+consPS :: Char -> PackedString -> PackedString
+consPS c cs = packString (c : (unpackPS cs)) -- ToDo:better
+
+packString :: [Char] -> PackedString
+packString str = runST (packStringST str)
+
+packStringST :: [Char] -> ST s PackedString
+packStringST str =
+ let len = length str in
+ packNCharsST len str
+
+packNCharsST :: Int -> [Char] -> ST s PackedString
+packNCharsST (I# length#) str =
+ {-
+ allocate an array that will hold the string
+ (not forgetting the NUL byte at the end)
+ -}
+ new_ps_array (length# +# 1#) >>= \ ch_array ->
+ -- fill in packed string from "str"
+ fill_in ch_array 0# str >>
+ -- freeze the puppy:
+ freeze_ps_array ch_array length# >>= \ (ByteArray _ _ frozen#) ->
+ let has_null = byteArrayHasNUL# frozen# length# in
+ return (PS frozen# length# has_null)
+ where
+ fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()
+ fill_in arr_in# idx [] =
+ write_ps_array arr_in# idx (chr# 0#) >>
+ return ()
+
+ fill_in arr_in# idx (C# c : cs) =
+ write_ps_array arr_in# idx c >>
+ fill_in arr_in# (idx +# 1#) cs
+
+byteArrayToPS :: ByteArray Int -> PackedString
+byteArrayToPS (ByteArray l u frozen#) =
+ let
+ ixs = (l,u)
+ n# =
+ case (
+ if null (range ixs)
+ then 0
+ else ((index ixs u) + 1)
+ ) of { I# x -> x }
+ in
+ PS frozen# n# (byteArrayHasNUL# frozen# n#)
+
+-- byteArray is zero-terminated, make everything upto it
+-- a packed string.
+cByteArrayToPS :: ByteArray Int -> PackedString
+cByteArrayToPS (ByteArray l u frozen#) =
+ let
+ ixs = (l,u)
+ n# =
+ case (
+ if null (range ixs)
+ then 0
+ else ((index ixs u) + 1)
+ ) of { I# x -> x }
+ len# = findNull 0#
+
+ findNull i#
+ | i# ==# n# = n#
+ | ch# `eqChar#` '\0'# = i# -- everything upto the sentinel
+ | otherwise = findNull (i# +# 1#)
+ where
+ ch# = indexCharArray# frozen# i#
+ in
+ PS frozen# len# False
+
+unsafeByteArrayToPS :: ByteArray a -> Int -> PackedString
+unsafeByteArrayToPS (ByteArray _ _ frozen#) (I# n#)
+ = PS frozen# n# (byteArrayHasNUL# frozen# n#)
+
+psToByteArray :: PackedString -> ByteArray Int
+psToByteArray (PS bytes n _) = ByteArray 0 (I# (n -# 1#)) bytes
+
+psToByteArray (CPS addr len#)
+ = let
+ len = I# len#
+ byte_array_form = packCBytes len (Ptr addr)
+ in
+ case byte_array_form of { PS bytes _ _ ->
+ ByteArray 0 (len - 1) bytes }
+
+-- isCString is useful when passing PackedStrings to the
+-- outside world, and need to figure out whether you can
+-- pass it as an Addr or ByteArray.
+--
+isCString :: PackedString -> Bool
+isCString (CPS _ _ ) = True
+isCString _ = False
+
+-- psToCString doesn't add a zero terminator!
+-- this doesn't appear to be very useful --SDM
+psToCString :: PackedString -> Ptr a
+psToCString (CPS addr _) = (Ptr addr)
+psToCString (PS bytes l# _) =
+ unsafePerformIO $ do
+ stuff <- mallocBytes (I# (l# +# 1#))
+ let
+ fill_in n# i#
+ | n# ==# 0# = return ()
+ | otherwise = do
+ let ch# = indexCharArray# bytes i#
+ pokeByteOff stuff (I# i#) (castCharToCChar (C# ch#))
+ fill_in (n# -# 1#) (i# +# 1#)
+ fill_in l# 0#
+ pokeByteOff stuff (I# l#) (C# '\0'#)
+ return stuff
+
+-- -----------------------------------------------------------------------------
+-- Destructor functions (taking PackedStrings apart)
+
+-- OK, but this code gets *hammered*:
+-- unpackPS ps
+-- = [ indexPS ps n | n <- [ 0::Int .. lengthPS ps - 1 ] ]
+
+unpackPS :: PackedString -> [Char]
+unpackPS (PS bytes len _) = unpack 0#
+ where
+ unpack nh
+ | nh >=# len = []
+ | otherwise = C# ch : unpack (nh +# 1#)
+ where
+ ch = indexCharArray# bytes nh
+
+unpackPS (CPS addr _) = unpack 0#
+ where
+ unpack nh
+ | ch `eqChar#` '\0'# = []
+ | otherwise = C# ch : unpack (nh +# 1#)
+ where
+ ch = indexCharOffAddr# addr nh
+
+unpackNBytesPS :: PackedString -> Int -> [Char]
+unpackNBytesPS ps len@(I# l#)
+ | len < 0 = error ("PackedString.unpackNBytesPS: negative length "++ show len)
+ | len == 0 = []
+ | otherwise =
+ case ps of
+ PS bytes len# has_null -> unpackPS (PS bytes (min# len# l#) has_null)
+ CPS a len# -> unpackPS (CPS a (min# len# l#))
+ where
+ min# x# y#
+ | x# <# y# = x#
+ | otherwise = y#
+
+unpackPSIO :: PackedString -> IO String
+unpackPSIO ps@(PS bytes _ _) = return (unpackPS ps)
+unpackPSIO (CPS addr _) = unpack 0#
+ where
+ unpack nh = do
+ ch <- peekByteOff (Ptr addr) (I# nh)
+ let c = castCCharToChar ch
+ if c == '\0'
+ then return []
+ else do
+ ls <- unpack (nh +# 1#)
+ return (c : ls)
+
+-- Output a packed string via a handle:
+
+hPutPS :: Handle -> PackedString -> IO ()
+hPutPS handle (CPS a# len#) = hPutBuf handle (Ptr a#) (I# len#)
+hPutPS handle (PS ba# len# _) = do
+ let mba = MutableByteArray (bottom::Int) bottom (unsafeCoerce# ba#)
+ hPutBufBA handle mba (I# len#)
+ where
+ bottom = error "hPutPS"
+
+-- The dual to @_putPS@, note that the size of the chunk specified
+-- is the upper bound of the size of the chunk returned.
+
+hGetPS :: Handle -> Int -> IO PackedString
+hGetPS hdl len@(I# len#)
+ | len# <=# 0# = return nilPS -- I'm being kind here.
+ | otherwise =
+ -- Allocate an array for system call to store its bytes into.
+ stToIO (new_ps_array len# ) >>= \ ch_arr ->
+ stToIO (freeze_ps_array ch_arr len#) >>= \ (ByteArray _ _ frozen#) ->
+ hGetBufBA hdl ch_arr len >>= \ (I# read#) ->
+ if read# ==# 0# then -- EOF or other error
+ ioError (userError "hGetPS: EOF reached or other error")
+ else
+ {-
+ The system call may not return the number of
+ bytes requested. Instead of failing with an error
+ if the number of bytes read is less than requested,
+ a packed string containing the bytes we did manage
+ to snarf is returned.
+ -}
+ let
+ has_null = byteArrayHasNUL# frozen# read#
+ in
+ return (PS frozen# read# has_null)
+
+-- -----------------------------------------------------------------------------
+-- List-mimicking functions for PackedStrings
+
+-- First, the basic functions that do look into the representation;
+-- @indexPS@ is the most important one.
+
+lengthPS :: PackedString -> Int
+lengthPS ps = I# (lengthPS# ps)
+
+{-# INLINE lengthPS# #-}
+
+lengthPS# :: PackedString -> Int#
+lengthPS# (PS _ i _) = i
+lengthPS# (CPS _ i) = i
+
+{-# INLINE strlen# #-}
+
+strlen# :: Addr# -> Int
+strlen# a
+ = unsafePerformIO (
+ _ccall_ strlen (Ptr a) >>= \ len@(I# _) ->
+ return len
+ )
+
+byteArrayHasNUL# :: ByteArray# -> Int#{-length-} -> Bool
+byteArrayHasNUL# bs len
+ = unsafePerformIO (
+ _ccall_ byteArrayHasNUL__ ba (I# len) >>= \ (I# res) ->
+ return (
+ if res ==# 0# then False else True
+ ))
+ where
+ ba = ByteArray 0 (I# (len -# 1#)) bs
+
+-----------------------
+
+indexPS :: PackedString -> Int -> Char
+indexPS ps (I# n) = C# (indexPS# ps n)
+
+{-# INLINE indexPS# #-}
+
+indexPS# :: PackedString -> Int# -> Char#
+indexPS# (PS bs i _) n
+ = --ASSERT (n >=# 0# && n <# i) -- error checking: my eye! (WDP 94/10)
+ indexCharArray# bs n
+
+indexPS# (CPS a _) n
+ = indexCharOffAddr# a n
+
+-- Now, the rest of the functions can be defined without digging
+-- around in the representation.
+
+headPS :: PackedString -> Char
+headPS ps
+ | nullPS ps = error "headPS: head []"
+ | otherwise = C# (indexPS# ps 0#)
+
+tailPS :: PackedString -> PackedString
+tailPS ps
+ | len <=# 0# = error "tailPS: tail []"
+ | len ==# 1# = nilPS
+ | otherwise = substrPS# ps 1# (len -# 1#)
+ where
+ len = lengthPS# ps
+
+nullPS :: PackedString -> Bool
+nullPS (PS _ i _) = i ==# 0#
+nullPS (CPS _ i) = i ==# 0#
+
+appendPS :: PackedString -> PackedString -> PackedString
+appendPS xs ys
+ | nullPS xs = ys
+ | nullPS ys = xs
+ | otherwise = concatPS [xs,ys]
+
+mapPS :: (Char -> Char) -> PackedString -> PackedString {-or String?-}
+mapPS f xs =
+ if nullPS xs then
+ xs
+ else
+ runST (
+ new_ps_array (length +# 1#) >>= \ ps_arr ->
+ whizz ps_arr length 0# >>
+ freeze_ps_array ps_arr length >>= \ (ByteArray _ _ frozen#) ->
+ let has_null = byteArrayHasNUL# frozen# length in
+ return (PS frozen# length has_null))
+ where
+ length = lengthPS# xs
+
+ whizz :: MutableByteArray s Int -> Int# -> Int# -> ST s ()
+ whizz arr# n i
+ | n ==# 0#
+ = write_ps_array arr# i (chr# 0#) >>
+ return ()
+ | otherwise
+ = let
+ ch = indexPS# xs i
+ in
+ write_ps_array arr# i (case f (C# ch) of { (C# x) -> x}) >>
+ whizz arr# (n -# 1#) (i +# 1#)
+
+filterPS :: (Char -> Bool) -> PackedString -> PackedString {-or String?-}
+filterPS pred ps =
+ if nullPS ps then
+ ps
+ else
+ {-
+ Filtering proceeds as follows:
+
+ * traverse the list, applying the pred. to each element,
+ remembering the positions where it was satisfied.
+
+ Encode these positions using a run-length encoding of the gaps
+ between the matching positions.
+
+ * Allocate a MutableByteArray in the heap big enough to hold
+ all the matched entries, and copy the elements that matched over.
+
+ A better solution that merges the scan&copy passes into one,
+ would be to copy the filtered elements over into a growable
+ buffer. No such operation currently supported over
+ MutableByteArrays (could of course use malloc&realloc)
+ But, this solution may in the case of repeated realloc's
+ be worse than the current solution.
+ -}
+ runST (
+ let
+ (rle,len_filtered) = filter_ps (len# -# 1#) 0# 0# []
+ len_filtered# = case len_filtered of { I# x# -> x#}
+ in
+ if len# ==# len_filtered# then
+ {- not much filtering as everything passed through. -}
+ return ps
+ else if len_filtered# ==# 0# then
+ return nilPS
+ else
+ new_ps_array (len_filtered# +# 1#) >>= \ ps_arr ->
+ copy_arr ps_arr rle 0# 0# >>
+ freeze_ps_array ps_arr len_filtered# >>= \ (ByteArray _ _ frozen#) ->
+ let has_null = byteArrayHasNUL# frozen# len_filtered# in
+ return (PS frozen# len_filtered# has_null))
+ where
+ len# = lengthPS# ps
+
+ matchOffset :: Int# -> [Char] -> (Int,[Char])
+ matchOffset off [] = (I# off,[])
+ matchOffset off (C# c:cs) =
+ let
+ x = ord# c
+ off' = off +# x
+ in
+ if x==# 0# then -- escape code, add 255#
+ matchOffset off' cs
+ else
+ (I# off', cs)
+
+ copy_arr :: MutableByteArray s Int -> [Char] -> Int# -> Int# -> ST s ()
+ copy_arr _ [_] _ _ = return ()
+ copy_arr arr# ls n i =
+ let
+ (x,ls') = matchOffset 0# ls
+ n' = n +# (case x of { (I# x#) -> x#}) -# 1#
+ ch = indexPS# ps n'
+ in
+ write_ps_array arr# i ch >>
+ copy_arr arr# ls' (n' +# 1#) (i +# 1#)
+
+ esc :: Int# -> Int# -> [Char] -> [Char]
+ esc v 0# ls = (C# (chr# v)):ls
+ esc v n ls = esc v (n -# 1#) (C# (chr# 0#):ls)
+
+ filter_ps :: Int# -> Int# -> Int# -> [Char] -> ([Char],Int)
+ filter_ps n hits run acc
+ | n <# 0# =
+ let
+ escs = run `quotInt#` 255#
+ v = run `remInt#` 255#
+ in
+ (esc (v +# 1#) escs acc, I# hits)
+ | otherwise
+ = let
+ ch = indexPS# ps n
+ n' = n -# 1#
+ in
+ if pred (C# ch) then
+ let
+ escs = run `quotInt#` 255#
+ v = run `remInt#` 255#
+ acc' = esc (v +# 1#) escs acc
+ in
+ filter_ps n' (hits +# 1#) 0# acc'
+ else
+ filter_ps n' hits (run +# 1#) acc
+
+
+foldlPS :: (a -> Char -> a) -> a -> PackedString -> a
+foldlPS f b ps
+ = if nullPS ps then
+ b
+ else
+ whizzLR b 0#
+ where
+ len = lengthPS# ps
+
+ --whizzLR :: a -> Int# -> a
+ whizzLR b idx
+ | idx ==# len = b
+ | otherwise = whizzLR (f b (C# (indexPS# ps idx))) (idx +# 1#)
+
+
+foldrPS :: (Char -> a -> a) -> a -> PackedString -> a
+foldrPS f v ps
+ | nullPS ps = v
+ | otherwise = whizzRL v len
+ where
+ len = lengthPS# ps
+
+ --whizzRL :: a -> Int# -> a
+ whizzRL b idx
+ | idx <# 0# = b
+ | otherwise = whizzRL (f (C# (indexPS# ps idx)) b) (idx -# 1#)
+
+takePS :: Int -> PackedString -> PackedString
+takePS (I# n) ps
+ | n ==# 0# = nilPS
+ | otherwise = substrPS# ps 0# (n -# 1#)
+
+dropPS :: Int -> PackedString -> PackedString
+dropPS (I# n) ps
+ | n ==# len = nilPS
+ | otherwise = substrPS# ps n (lengthPS# ps -# 1#)
+ where
+ len = lengthPS# ps
+
+splitAtPS :: Int -> PackedString -> (PackedString, PackedString)
+splitAtPS n ps = (takePS n ps, dropPS n ps)
+
+takeWhilePS :: (Char -> Bool) -> PackedString -> PackedString
+takeWhilePS pred ps
+ = let
+ break_pt = char_pos_that_dissatisfies
+ (\ c -> pred (C# c))
+ ps
+ (lengthPS# ps)
+ 0#
+ in
+ if break_pt ==# 0# then
+ nilPS
+ else
+ substrPS# ps 0# (break_pt -# 1#)
+
+dropWhilePS :: (Char -> Bool) -> PackedString -> PackedString
+dropWhilePS pred ps
+ = let
+ len = lengthPS# ps
+ break_pt = char_pos_that_dissatisfies
+ (\ c -> pred (C# c))
+ ps
+ len
+ 0#
+ in
+ if len ==# break_pt then
+ nilPS
+ else
+ substrPS# ps break_pt (len -# 1#)
+
+elemPS :: Char -> PackedString -> Bool
+elemPS (C# ch) ps
+ = let
+ len = lengthPS# ps
+ break_pt = first_char_pos_that_satisfies
+ (`eqChar#` ch)
+ ps
+ len
+ 0#
+ in
+ break_pt <# len
+
+char_pos_that_dissatisfies :: (Char# -> Bool) -> PackedString -> Int# -> Int# -> Int#
+
+char_pos_that_dissatisfies p ps len pos
+ | pos >=# len = pos -- end
+ | p (indexPS# ps pos) = -- predicate satisfied; keep going
+ char_pos_that_dissatisfies p ps len (pos +# 1#)
+ | otherwise = pos -- predicate not satisfied
+
+first_char_pos_that_satisfies :: (Char# -> Bool) -> PackedString -> Int# -> Int# -> Int#
+first_char_pos_that_satisfies p ps len pos
+ | pos >=# len = pos -- end
+ | p (indexPS# ps pos) = pos -- got it!
+ | otherwise = first_char_pos_that_satisfies p ps len (pos +# 1#)
+
+-- ToDo: could certainly go quicker
+spanPS :: (Char -> Bool) -> PackedString -> (PackedString, PackedString)
+spanPS p ps = (takeWhilePS p ps, dropWhilePS p ps)
+
+breakPS :: (Char -> Bool) -> PackedString -> (PackedString, PackedString)
+breakPS p ps = spanPS (not . p) ps
+
+linesPS :: PackedString -> [PackedString]
+linesPS ps = splitPS '\n' ps
+
+wordsPS :: PackedString -> [PackedString]
+wordsPS ps = splitWithPS isSpace ps
+
+reversePS :: PackedString -> PackedString
+reversePS ps =
+ if nullPS ps then -- don't create stuff unnecessarily.
+ ps
+ else
+ runST (
+ new_ps_array (length +# 1#) >>= \ arr# -> -- incl NUL byte!
+ fill_in arr# (length -# 1#) 0# >>
+ freeze_ps_array arr# length >>= \ (ByteArray _ _ frozen#) ->
+ let has_null = byteArrayHasNUL# frozen# length in
+ return (PS frozen# length has_null))
+ where
+ length = lengthPS# ps
+
+ fill_in :: MutableByteArray s Int -> Int# -> Int# -> ST s ()
+ fill_in arr_in# n i =
+ let
+ ch = indexPS# ps n
+ in
+ write_ps_array arr_in# i ch >>
+ if n ==# 0# then
+ write_ps_array arr_in# (i +# 1#) (chr# 0#) >>
+ return ()
+ else
+ fill_in arr_in# (n -# 1#) (i +# 1#)
+
+concatPS :: [PackedString] -> PackedString
+concatPS [] = nilPS
+concatPS pss
+ = let
+ tot_len# = case (foldr ((+) . lengthPS) 0 pss) of { I# x -> x }
+ in
+ runST (
+ new_ps_array (tot_len# +# 1#) >>= \ arr# -> -- incl NUL byte!
+ packum arr# pss 0# >>
+ freeze_ps_array arr# tot_len# >>= \ (ByteArray _ _ frozen#) ->
+
+ let has_null = byteArrayHasNUL# frozen# tot_len# in
+
+ return (PS frozen# tot_len# has_null)
+ )
+ where
+ packum :: MutableByteArray s Int -> [PackedString] -> Int# -> ST s ()
+
+ packum arr [] pos
+ = write_ps_array arr pos (chr# 0#) >>
+ return ()
+ packum arr (ps : pss) pos
+ = fill arr pos ps 0# (lengthPS# ps) >>= \ (I# next_pos) ->
+ packum arr pss next_pos
+
+ fill :: MutableByteArray s Int -> Int# -> PackedString -> Int# -> Int# -> ST s Int
+
+ fill arr arr_i ps ps_i ps_len
+ | ps_i ==# ps_len
+ = return (I# (arr_i +# ps_len))
+ | otherwise
+ = write_ps_array arr (arr_i +# ps_i) (indexPS# ps ps_i) >>
+ fill arr arr_i ps (ps_i +# 1#) ps_len
+
+------------------------------------------------------------
+joinPS :: PackedString -> [PackedString] -> PackedString
+joinPS filler pss = concatPS (splice pss)
+ where
+ splice [] = []
+ splice [x] = [x]
+ splice (x:y:xs) = x:filler:splice (y:xs)
+
+-- ToDo: the obvious generalisation
+{-
+ Some properties that hold:
+
+ * splitPS x ls = ls'
+ where False = any (map (x `elemPS`) ls')
+ False = any (map (nullPS) ls')
+
+ * all x's have been chopped out.
+ * no empty PackedStrings in returned list. A conseq.
+ of this is:
+ splitPS x nilPS = []
+
+
+ * joinPS (packString [x]) (_splitPS x ls) = ls
+
+-}
+
+splitPS :: Char -> PackedString -> [PackedString]
+splitPS (C# ch) = splitWithPS (\ (C# c) -> c `eqChar#` ch)
+
+splitWithPS :: (Char -> Bool) -> PackedString -> [PackedString]
+splitWithPS pred ps =
+ splitify 0#
+ where
+ len = lengthPS# ps
+
+ splitify n
+ | n >=# len = []
+ | otherwise =
+ let
+ break_pt =
+ first_char_pos_that_satisfies
+ (\ c -> pred (C# c))
+ ps
+ len
+ n
+ in
+ if break_pt ==# n then -- immediate match, no substring to cut out.
+ splitify (break_pt +# 1#)
+ else
+ substrPS# ps n (break_pt -# 1#): -- leave out the matching character
+ splitify (break_pt +# 1#)
+
+-- -----------------------------------------------------------------------------
+-- Local utility functions
+
+-- The definition of @_substrPS@ is essentially:
+-- @take (end - begin + 1) (drop begin str)@.
+
+substrPS :: PackedString -> Int -> Int -> PackedString
+substrPS ps (I# begin) (I# end) = substrPS# ps begin end
+
+substrPS# :: PackedString -> Int# -> Int# -> PackedString
+substrPS# ps s e
+ | s <# 0# || s >=# len || result_len# <=# 0#
+ = nilPS
+
+ | otherwise
+ = runST (
+ new_ps_array (result_len# +# 1#) >>= \ ch_arr -> -- incl NUL byte!
+ fill_in ch_arr 0# >>
+ freeze_ps_array ch_arr result_len# >>= \ (ByteArray _ _ frozen#) ->
+
+ let has_null = byteArrayHasNUL# frozen# result_len# in
+
+ return (PS frozen# result_len# has_null)
+ )
+ where
+ len = lengthPS# ps
+
+ result_len# = (if e <# len then (e +# 1#) else len) -# s
+
+ -----------------------
+ fill_in :: MutableByteArray s Int -> Int# -> ST s ()
+
+ fill_in arr_in# idx
+ | idx ==# result_len#
+ = write_ps_array arr_in# idx (chr# 0#) >>
+ return ()
+ | otherwise
+ = let
+ ch = indexPS# ps (s +# idx)
+ in
+ write_ps_array arr_in# idx ch >>
+ fill_in arr_in# (idx +# 1#)
+
+-- -----------------------------------------------------------------------------
+-- Packing and unpacking C strings
+
+cStringToPS :: Ptr a -> PackedString
+cStringToPS (Ptr a#) = -- the easy one; we just believe the caller
+ CPS a# len
+ where
+ len = case (strlen# a#) of { I# x -> x }
+
+packCBytes :: Int -> Ptr a -> PackedString
+packCBytes len addr = runST (packCBytesST len addr)
+
+packCBytesST :: Int -> Ptr a -> ST s PackedString
+packCBytesST (I# length#) (Ptr addr) =
+ {-
+ allocate an array that will hold the string
+ (not forgetting the NUL byte at the end)
+ -}
+ new_ps_array (length# +# 1#) >>= \ ch_array ->
+ -- fill in packed string from "addr"
+ fill_in ch_array 0# >>
+ -- freeze the puppy:
+ freeze_ps_array ch_array length# >>= \ (ByteArray _ _ frozen#) ->
+ let has_null = byteArrayHasNUL# frozen# length# in
+ return (PS frozen# length# has_null)
+ where
+ fill_in :: MutableByteArray s Int -> Int# -> ST s ()
+
+ fill_in arr_in# idx
+ | idx ==# length#
+ = write_ps_array arr_in# idx (chr# 0#) >>
+ return ()
+ | otherwise
+ = case (indexCharOffAddr# addr idx) of { ch ->
+ write_ps_array arr_in# idx ch >>
+ fill_in arr_in# (idx +# 1#) }
diff --git a/libraries/base/Data/Ratio.hs b/libraries/base/Data/Ratio.hs
new file mode 100644
index 0000000000..42426ce703
--- /dev/null
+++ b/libraries/base/Data/Ratio.hs
@@ -0,0 +1,81 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.Ratio
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Ratio.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Standard functions on rational numbers
+--
+-----------------------------------------------------------------------------
+
+module Data.Ratio
+ ( Ratio
+ , Rational
+ , (%) -- :: (Integral a) => a -> a -> Ratio a
+ , numerator -- :: (Integral a) => Ratio a -> a
+ , denominator -- :: (Integral a) => Ratio a -> a
+ , approxRational -- :: (RealFrac a) => a -> a -> Rational
+
+ -- Ratio instances:
+ -- (Integral a) => Eq (Ratio a)
+ -- (Integral a) => Ord (Ratio a)
+ -- (Integral a) => Num (Ratio a)
+ -- (Integral a) => Real (Ratio a)
+ -- (Integral a) => Fractional (Ratio a)
+ -- (Integral a) => RealFrac (Ratio a)
+ -- (Integral a) => Enum (Ratio a)
+ -- (Read a, Integral a) => Read (Ratio a)
+ -- (Integral a) => Show (Ratio a)
+
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Real -- The basic defns for Ratio
+#endif
+
+-- -----------------------------------------------------------------------------
+-- approxRational
+
+-- @approxRational@, applied to two real fractional numbers x and epsilon,
+-- returns the simplest rational number within epsilon of x. A rational
+-- number n%d in reduced form is said to be simpler than another n'%d' if
+-- abs n <= abs n' && d <= d'. Any real interval contains a unique
+-- simplest rational; here, for simplicity, we assume a closed rational
+-- interval. If such an interval includes at least one whole number, then
+-- the simplest rational is the absolutely least whole number. Otherwise,
+-- the bounds are of the form q%1 + r%d and q%1 + r'%d', where abs r < d
+-- and abs r' < d', and the simplest rational is q%1 + the reciprocal of
+-- the simplest rational between d'%r' and d%r.
+
+approxRational :: (RealFrac a) => a -> a -> Rational
+approxRational rat eps = simplest (rat-eps) (rat+eps)
+ where simplest x y | y < x = simplest y x
+ | x == y = xr
+ | x > 0 = simplest' n d n' d'
+ | y < 0 = - simplest' (-n') d' (-n) d
+ | otherwise = 0 :% 1
+ where xr = toRational x
+ n = numerator xr
+ d = denominator xr
+ nd' = toRational y
+ n' = numerator nd'
+ d' = denominator nd'
+
+ simplest' n d n' d' -- assumes 0 < n%d < n'%d'
+ | r == 0 = q :% 1
+ | q /= q' = (q+1) :% 1
+ | otherwise = (q*n''+d'') :% n''
+ where (q,r) = quotRem n d
+ (q',r') = quotRem n' d'
+ nd'' = simplest' d' r' d r
+ n'' = numerator nd''
+ d'' = denominator nd''
+
diff --git a/libraries/base/Data/STRef.hs b/libraries/base/Data/STRef.hs
new file mode 100644
index 0000000000..01e5cb0fa6
--- /dev/null
+++ b/libraries/base/Data/STRef.hs
@@ -0,0 +1,33 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Data.STRef
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: STRef.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Mutable references in the ST monad.
+--
+-----------------------------------------------------------------------------
+
+module Data.STRef (
+ STRef, -- abstract, instance Eq
+ newSTRef, -- :: a -> ST s (STRef s a)
+ readSTRef, -- :: STRef s a -> ST s a
+ writeSTRef -- :: STRef s a -> a -> ST s ()
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.STRef
+#endif
+
+import Data.Dynamic
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE2(STRef,stRefTc,"STRef")
diff --git a/libraries/base/Data/Word.hs b/libraries/base/Data/Word.hs
new file mode 100644
index 0000000000..7fbdc87ebb
--- /dev/null
+++ b/libraries/base/Data/Word.hs
@@ -0,0 +1,38 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module :
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Word.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- Sized unsigned integer types.
+--
+-----------------------------------------------------------------------------
+
+module Data.Word
+ ( Word
+ , Word8
+ , Word16
+ , Word32
+ , Word64
+ -- instances: Eq, Ord, Num, Bounded, Real, Integral, Ix, Enum, Read,
+ -- Show, Bits, CCallable, CReturnable (last two are GHC specific.)
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Word
+#endif
+
+import Data.Dynamic
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(Word8,word8Tc, "Word8" )
+INSTANCE_TYPEABLE0(Word16,word16Tc,"Word16")
+INSTANCE_TYPEABLE0(Word32,word32Tc,"Word32")
+INSTANCE_TYPEABLE0(Word64,word64Tc,"Word64")
diff --git a/libraries/base/Debug/Trace.hs b/libraries/base/Debug/Trace.hs
new file mode 100644
index 0000000000..d5a012a73b
--- /dev/null
+++ b/libraries/base/Debug/Trace.hs
@@ -0,0 +1,41 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Debug.Trace
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Trace.hs,v 1.1 2001/06/28 14:15:02 simonmar Exp $
+--
+-- The trace function.
+--
+-----------------------------------------------------------------------------
+
+module Debug.Trace (
+ trace -- :: String -> a -> a
+ ) where
+
+import Prelude
+import System.IO.Unsafe
+import System.IO
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.IOBase
+import GHC.Handle
+#endif
+
+#ifdef __GLASGOW_HASKELL__
+{-# NOINLINE trace #-}
+trace :: String -> a -> a
+trace string expr = unsafePerformIO $ do
+ hPutStr stderr string
+ hPutChar stderr '\n'
+ fd <- withHandle_ "trace" stderr $ (return.haFD)
+ postTraceHook fd
+ return expr
+
+foreign import "PostTraceHook" postTraceHook :: Int -> IO ()
+#endif
diff --git a/libraries/base/Foreign.hs b/libraries/base/Foreign.hs
new file mode 100644
index 0000000000..75639e4ed7
--- /dev/null
+++ b/libraries/base/Foreign.hs
@@ -0,0 +1,44 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Foreign.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-- A collection of data types, classes, and functions for interfacing
+-- with another programming language. This is only a convenience module
+-- in the future, but currently it has the additional task of hiding
+-- those entities exported from other modules, which are not part of the
+-- FFI proposal.
+--
+-----------------------------------------------------------------------------
+
+module Foreign
+ ( module Data.Int
+ , module Data.Word
+ , module Foreign.Ptr
+ , module Foreign.ForeignPtr
+ , module Foreign.StablePtr
+ , module Foreign.Storable
+ , module Foreign.Marshal.Alloc
+ , module Foreign.Marshal.Array
+ , module Foreign.Marshal.Error
+ , module Foreign.Marshal.Utils
+ ) where
+
+import Data.Int
+import Data.Word
+import Foreign.Ptr
+import Foreign.ForeignPtr
+import Foreign.StablePtr
+import Foreign.Storable
+import Foreign.Marshal.Alloc
+import Foreign.Marshal.Array
+import Foreign.Marshal.Error
+import Foreign.Marshal.Utils
diff --git a/libraries/base/Foreign/C.hs b/libraries/base/Foreign/C.hs
new file mode 100644
index 0000000000..b91d6d79ce
--- /dev/null
+++ b/libraries/base/Foreign/C.hs
@@ -0,0 +1,28 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.C
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: C.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Bundles the C specific FFI library functionality
+--
+-----------------------------------------------------------------------------
+
+module Foreign.C
+ ( module Foreign.C.Types
+ , module Foreign.C.TypesISO
+ , module Foreign.C.String
+ , module Foreign.C.Error
+ ) where
+
+import Foreign.C.Types
+import Foreign.C.TypesISO
+import Foreign.C.String
+import Foreign.C.Error
diff --git a/libraries/base/Foreign/C/Error.hs b/libraries/base/Foreign/C/Error.hs
new file mode 100644
index 0000000000..3bba4ed55a
--- /dev/null
+++ b/libraries/base/Foreign/C/Error.hs
@@ -0,0 +1,514 @@
+{-# OPTIONS -fno-implicit-prelude -#include "HsCore.h" #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.C.Error
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Error.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- C-specific Marshalling support: Handling of C "errno" error codes
+--
+-----------------------------------------------------------------------------
+
+module Foreign.C.Error (
+
+ -- Haskell representation for "errno" values
+ --
+ Errno(..), -- instance: Eq
+ eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
+ eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
+ eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
+ eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
+ eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
+ eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
+ eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
+ eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
+ eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,
+ eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
+ ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
+ eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
+ eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
+ eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV,
+ -- :: Errno
+ isValidErrno, -- :: Errno -> Bool
+
+ -- access to the current thread's "errno" value
+ --
+ getErrno, -- :: IO Errno
+ resetErrno, -- :: IO ()
+
+ -- conversion of an "errno" value into IO error
+ --
+ errnoToIOError, -- :: String -- location
+ -- -> Errno -- errno
+ -- -> Maybe Handle -- handle
+ -- -> Maybe String -- filename
+ -- -> IOError
+
+ -- throw current "errno" value
+ --
+ throwErrno, -- :: String -> IO a
+
+ -- guards for IO operations that may fail
+ --
+ throwErrnoIf, -- :: (a -> Bool) -> String -> IO a -> IO a
+ throwErrnoIf_, -- :: (a -> Bool) -> String -> IO a -> IO ()
+ throwErrnoIfRetry, -- :: (a -> Bool) -> String -> IO a -> IO a
+ throwErrnoIfRetry_, -- :: (a -> Bool) -> String -> IO a -> IO ()
+ throwErrnoIfMinus1, -- :: Num a
+ -- => String -> IO a -> IO a
+ throwErrnoIfMinus1_, -- :: Num a
+ -- => String -> IO a -> IO ()
+ throwErrnoIfMinus1Retry,
+ -- :: Num a
+ -- => String -> IO a -> IO a
+ throwErrnoIfMinus1Retry_,
+ -- :: Num a
+ -- => String -> IO a -> IO ()
+ throwErrnoIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)
+ throwErrnoIfNullRetry,-- :: String -> IO (Ptr a) -> IO (Ptr a)
+
+ throwErrnoIfRetryMayBlock,
+ throwErrnoIfRetryMayBlock_,
+ throwErrnoIfMinus1RetryMayBlock,
+ throwErrnoIfMinus1RetryMayBlock_,
+ throwErrnoIfNullRetryMayBlock
+) where
+
+
+-- this is were we get the CCONST_XXX definitions from that configure
+-- calculated for us
+--
+#include "config.h"
+
+-- system dependent imports
+-- ------------------------
+
+-- GHC allows us to get at the guts inside IO errors/exceptions
+--
+#if __GLASGOW_HASKELL__
+import GHC.IOBase (Exception(..), IOException(..), IOErrorType(..))
+#endif /* __GLASGOW_HASKELL__ */
+
+
+-- regular imports
+-- ---------------
+
+import Foreign.Ptr
+import Foreign.C.Types
+import Foreign.C.String
+import Foreign.Marshal.Error ( void )
+import Data.Maybe
+
+#if __GLASGOW_HASKELL__
+import GHC.Storable
+import GHC.IOBase
+import GHC.Num
+import GHC.Base
+#else
+import System.IO ( IOError, Handle, ioError )
+#endif
+
+-- "errno" type
+-- ------------
+
+-- import of C function that gives address of errno
+--
+foreign import "ghcErrno" unsafe _errno :: Ptr CInt
+
+-- Haskell representation for "errno" values
+--
+newtype Errno = Errno CInt
+
+instance Eq Errno where
+ errno1@(Errno no1) == errno2@(Errno no2)
+ | isValidErrno errno1 && isValidErrno errno2 = no1 == no2
+ | otherwise = False
+
+-- common "errno" symbols
+--
+eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,
+ eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,
+ eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,
+ eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,
+ eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,
+ eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,
+ eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,
+ eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,
+ eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,
+ eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,
+ ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,
+ eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,
+ eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,
+ eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV :: Errno
+--
+-- the CCONST_XXX identifiers are cpp symbols whose value is computed by
+-- configure
+--
+eOK = Errno 0
+e2BIG = Errno (CCONST_E2BIG)
+eACCES = Errno (CCONST_EACCES)
+eADDRINUSE = Errno (CCONST_EADDRINUSE)
+eADDRNOTAVAIL = Errno (CCONST_EADDRNOTAVAIL)
+eADV = Errno (CCONST_EADV)
+eAFNOSUPPORT = Errno (CCONST_EAFNOSUPPORT)
+eAGAIN = Errno (CCONST_EAGAIN)
+eALREADY = Errno (CCONST_EALREADY)
+eBADF = Errno (CCONST_EBADF)
+eBADMSG = Errno (CCONST_EBADMSG)
+eBADRPC = Errno (CCONST_EBADRPC)
+eBUSY = Errno (CCONST_EBUSY)
+eCHILD = Errno (CCONST_ECHILD)
+eCOMM = Errno (CCONST_ECOMM)
+eCONNABORTED = Errno (CCONST_ECONNABORTED)
+eCONNREFUSED = Errno (CCONST_ECONNREFUSED)
+eCONNRESET = Errno (CCONST_ECONNRESET)
+eDEADLK = Errno (CCONST_EDEADLK)
+eDESTADDRREQ = Errno (CCONST_EDESTADDRREQ)
+eDIRTY = Errno (CCONST_EDIRTY)
+eDOM = Errno (CCONST_EDOM)
+eDQUOT = Errno (CCONST_EDQUOT)
+eEXIST = Errno (CCONST_EEXIST)
+eFAULT = Errno (CCONST_EFAULT)
+eFBIG = Errno (CCONST_EFBIG)
+eFTYPE = Errno (CCONST_EFTYPE)
+eHOSTDOWN = Errno (CCONST_EHOSTDOWN)
+eHOSTUNREACH = Errno (CCONST_EHOSTUNREACH)
+eIDRM = Errno (CCONST_EIDRM)
+eILSEQ = Errno (CCONST_EILSEQ)
+eINPROGRESS = Errno (CCONST_EINPROGRESS)
+eINTR = Errno (CCONST_EINTR)
+eINVAL = Errno (CCONST_EINVAL)
+eIO = Errno (CCONST_EIO)
+eISCONN = Errno (CCONST_EISCONN)
+eISDIR = Errno (CCONST_EISDIR)
+eLOOP = Errno (CCONST_ELOOP)
+eMFILE = Errno (CCONST_EMFILE)
+eMLINK = Errno (CCONST_EMLINK)
+eMSGSIZE = Errno (CCONST_EMSGSIZE)
+eMULTIHOP = Errno (CCONST_EMULTIHOP)
+eNAMETOOLONG = Errno (CCONST_ENAMETOOLONG)
+eNETDOWN = Errno (CCONST_ENETDOWN)
+eNETRESET = Errno (CCONST_ENETRESET)
+eNETUNREACH = Errno (CCONST_ENETUNREACH)
+eNFILE = Errno (CCONST_ENFILE)
+eNOBUFS = Errno (CCONST_ENOBUFS)
+eNODATA = Errno (CCONST_ENODATA)
+eNODEV = Errno (CCONST_ENODEV)
+eNOENT = Errno (CCONST_ENOENT)
+eNOEXEC = Errno (CCONST_ENOEXEC)
+eNOLCK = Errno (CCONST_ENOLCK)
+eNOLINK = Errno (CCONST_ENOLINK)
+eNOMEM = Errno (CCONST_ENOMEM)
+eNOMSG = Errno (CCONST_ENOMSG)
+eNONET = Errno (CCONST_ENONET)
+eNOPROTOOPT = Errno (CCONST_ENOPROTOOPT)
+eNOSPC = Errno (CCONST_ENOSPC)
+eNOSR = Errno (CCONST_ENOSR)
+eNOSTR = Errno (CCONST_ENOSTR)
+eNOSYS = Errno (CCONST_ENOSYS)
+eNOTBLK = Errno (CCONST_ENOTBLK)
+eNOTCONN = Errno (CCONST_ENOTCONN)
+eNOTDIR = Errno (CCONST_ENOTDIR)
+eNOTEMPTY = Errno (CCONST_ENOTEMPTY)
+eNOTSOCK = Errno (CCONST_ENOTSOCK)
+eNOTTY = Errno (CCONST_ENOTTY)
+eNXIO = Errno (CCONST_ENXIO)
+eOPNOTSUPP = Errno (CCONST_EOPNOTSUPP)
+ePERM = Errno (CCONST_EPERM)
+ePFNOSUPPORT = Errno (CCONST_EPFNOSUPPORT)
+ePIPE = Errno (CCONST_EPIPE)
+ePROCLIM = Errno (CCONST_EPROCLIM)
+ePROCUNAVAIL = Errno (CCONST_EPROCUNAVAIL)
+ePROGMISMATCH = Errno (CCONST_EPROGMISMATCH)
+ePROGUNAVAIL = Errno (CCONST_EPROGUNAVAIL)
+ePROTO = Errno (CCONST_EPROTO)
+ePROTONOSUPPORT = Errno (CCONST_EPROTONOSUPPORT)
+ePROTOTYPE = Errno (CCONST_EPROTOTYPE)
+eRANGE = Errno (CCONST_ERANGE)
+eREMCHG = Errno (CCONST_EREMCHG)
+eREMOTE = Errno (CCONST_EREMOTE)
+eROFS = Errno (CCONST_EROFS)
+eRPCMISMATCH = Errno (CCONST_ERPCMISMATCH)
+eRREMOTE = Errno (CCONST_ERREMOTE)
+eSHUTDOWN = Errno (CCONST_ESHUTDOWN)
+eSOCKTNOSUPPORT = Errno (CCONST_ESOCKTNOSUPPORT)
+eSPIPE = Errno (CCONST_ESPIPE)
+eSRCH = Errno (CCONST_ESRCH)
+eSRMNT = Errno (CCONST_ESRMNT)
+eSTALE = Errno (CCONST_ESTALE)
+eTIME = Errno (CCONST_ETIME)
+eTIMEDOUT = Errno (CCONST_ETIMEDOUT)
+eTOOMANYREFS = Errno (CCONST_ETOOMANYREFS)
+eTXTBSY = Errno (CCONST_ETXTBSY)
+eUSERS = Errno (CCONST_EUSERS)
+eWOULDBLOCK = Errno (CCONST_EWOULDBLOCK)
+eXDEV = Errno (CCONST_EXDEV)
+
+-- checks whether the given errno value is supported on the current
+-- architecture
+--
+isValidErrno :: Errno -> Bool
+--
+-- the configure script sets all invalid "errno"s to -1
+--
+isValidErrno (Errno errno) = errno /= -1
+
+
+-- access to the current thread's "errno" value
+-- --------------------------------------------
+
+-- yield the current thread's "errno" value
+--
+getErrno :: IO Errno
+getErrno = do e <- peek _errno; return (Errno e)
+
+-- set the current thread's "errno" value to 0
+--
+resetErrno :: IO ()
+resetErrno = poke _errno 0
+
+
+-- throw current "errno" value
+-- ---------------------------
+
+-- the common case: throw an IO error based on a textual description
+-- of the error location and the current thread's "errno" value
+--
+throwErrno :: String -> IO a
+throwErrno loc =
+ do
+ errno <- getErrno
+ ioError (errnoToIOError loc errno Nothing Nothing)
+
+
+-- guards for IO operations that may fail
+-- --------------------------------------
+
+-- guard an IO operation and throw an "errno" based exception of the result
+-- value of the IO operation meets the given predicate
+--
+throwErrnoIf :: (a -> Bool) -> String -> IO a -> IO a
+throwErrnoIf pred loc f =
+ do
+ res <- f
+ if pred res then throwErrno loc else return res
+
+-- as `throwErrnoIf', but discards the result
+--
+throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO ()
+throwErrnoIf_ pred loc f = void $ throwErrnoIf pred loc f
+
+-- as `throwErrnoIf', but retries interrupted IO operations (ie, those whose
+-- flag `EINTR')
+--
+throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a
+throwErrnoIfRetry pred loc f =
+ do
+ res <- f
+ if pred res
+ then do
+ err <- getErrno
+ if err == eINTR
+ then throwErrnoIfRetry pred loc f
+ else throwErrno loc
+ else return res
+
+-- as `throwErrnoIfRetry', but checks for operations that would block and
+-- executes an alternative action in that case.
+
+throwErrnoIfRetryMayBlock :: (a -> Bool) -> String -> IO a -> IO b -> IO a
+throwErrnoIfRetryMayBlock pred loc f on_block =
+ do
+ res <- f
+ if pred res
+ then do
+ err <- getErrno
+ if err == eINTR
+ then throwErrnoIfRetryMayBlock pred loc f on_block
+ else if err == eWOULDBLOCK || err == eAGAIN
+ then do on_block; throwErrnoIfRetryMayBlock pred loc f on_block
+ else throwErrno loc
+ else return res
+
+-- as `throwErrnoIfRetry', but discards the result
+--
+throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO ()
+throwErrnoIfRetry_ pred loc f = void $ throwErrnoIfRetry pred loc f
+
+-- as `throwErrnoIfRetryMayBlock', but discards the result
+--
+throwErrnoIfRetryMayBlock_ :: (a -> Bool) -> String -> IO a -> IO b -> IO ()
+throwErrnoIfRetryMayBlock_ pred loc f on_block
+ = void $ throwErrnoIfRetryMayBlock pred loc f on_block
+
+-- throws "errno" if a result of "-1" is returned
+--
+throwErrnoIfMinus1 :: Num a => String -> IO a -> IO a
+throwErrnoIfMinus1 = throwErrnoIf (== -1)
+
+-- as `throwErrnoIfMinus1', but discards the result
+--
+throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
+throwErrnoIfMinus1_ = throwErrnoIf_ (== -1)
+
+-- throws "errno" if a result of "-1" is returned, but retries in case of an
+-- interrupted operation
+--
+throwErrnoIfMinus1Retry :: Num a => String -> IO a -> IO a
+throwErrnoIfMinus1Retry = throwErrnoIfRetry (== -1)
+
+-- as `throwErrnoIfMinus1', but discards the result
+--
+throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
+throwErrnoIfMinus1Retry_ = throwErrnoIfRetry_ (== -1)
+
+-- as throwErrnoIfMinus1Retry, but checks for operations that would block
+--
+throwErrnoIfMinus1RetryMayBlock :: Num a => String -> IO a -> IO b -> IO a
+throwErrnoIfMinus1RetryMayBlock = throwErrnoIfRetryMayBlock (== -1)
+
+-- as `throwErrnoIfMinus1RetryMayBlock', but discards the result
+--
+throwErrnoIfMinus1RetryMayBlock_ :: Num a => String -> IO a -> IO b -> IO ()
+throwErrnoIfMinus1RetryMayBlock_ = throwErrnoIfRetryMayBlock_ (== -1)
+
+-- throws "errno" if a result of a NULL pointer is returned
+--
+throwErrnoIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
+throwErrnoIfNull = throwErrnoIf (== nullPtr)
+
+-- throws "errno" if a result of a NULL pointer is returned, but retries in
+-- case of an interrupted operation
+--
+throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
+throwErrnoIfNullRetry = throwErrnoIfRetry (== nullPtr)
+
+-- as throwErrnoIfNullRetry, but checks for operations that would block
+--
+throwErrnoIfNullRetryMayBlock :: String -> IO (Ptr a) -> IO b -> IO (Ptr a)
+throwErrnoIfNullRetryMayBlock = throwErrnoIfRetryMayBlock (== nullPtr)
+
+-- conversion of an "errno" value into IO error
+-- --------------------------------------------
+
+-- convert a location string, an "errno" value, an optional handle,
+-- and an optional filename into a matching IO error
+--
+errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
+errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do
+ str <- strerror errno >>= peekCString
+#if __GLASGOW_HASKELL__
+ return (IOException (IOError maybeHdl errType loc str maybeName))
+ where
+ errType
+ | errno == eOK = OtherError
+ | errno == e2BIG = ResourceExhausted
+ | errno == eACCES = PermissionDenied
+ | errno == eADDRINUSE = ResourceBusy
+ | errno == eADDRNOTAVAIL = UnsupportedOperation
+ | errno == eADV = OtherError
+ | errno == eAFNOSUPPORT = UnsupportedOperation
+ | errno == eAGAIN = ResourceExhausted
+ | errno == eALREADY = AlreadyExists
+ | errno == eBADF = OtherError
+ | errno == eBADMSG = InappropriateType
+ | errno == eBADRPC = OtherError
+ | errno == eBUSY = ResourceBusy
+ | errno == eCHILD = NoSuchThing
+ | errno == eCOMM = ResourceVanished
+ | errno == eCONNABORTED = OtherError
+ | errno == eCONNREFUSED = NoSuchThing
+ | errno == eCONNRESET = ResourceVanished
+ | errno == eDEADLK = ResourceBusy
+ | errno == eDESTADDRREQ = InvalidArgument
+ | errno == eDIRTY = UnsatisfiedConstraints
+ | errno == eDOM = InvalidArgument
+ | errno == eDQUOT = PermissionDenied
+ | errno == eEXIST = AlreadyExists
+ | errno == eFAULT = OtherError
+ | errno == eFBIG = PermissionDenied
+ | errno == eFTYPE = InappropriateType
+ | errno == eHOSTDOWN = NoSuchThing
+ | errno == eHOSTUNREACH = NoSuchThing
+ | errno == eIDRM = ResourceVanished
+ | errno == eILSEQ = InvalidArgument
+ | errno == eINPROGRESS = AlreadyExists
+ | errno == eINTR = Interrupted
+ | errno == eINVAL = InvalidArgument
+ | errno == eIO = HardwareFault
+ | errno == eISCONN = AlreadyExists
+ | errno == eISDIR = InappropriateType
+ | errno == eLOOP = InvalidArgument
+ | errno == eMFILE = ResourceExhausted
+ | errno == eMLINK = ResourceExhausted
+ | errno == eMSGSIZE = ResourceExhausted
+ | errno == eMULTIHOP = UnsupportedOperation
+ | errno == eNAMETOOLONG = InvalidArgument
+ | errno == eNETDOWN = ResourceVanished
+ | errno == eNETRESET = ResourceVanished
+ | errno == eNETUNREACH = NoSuchThing
+ | errno == eNFILE = ResourceExhausted
+ | errno == eNOBUFS = ResourceExhausted
+ | errno == eNODATA = NoSuchThing
+ | errno == eNODEV = NoSuchThing
+ | errno == eNOENT = NoSuchThing
+ | errno == eNOEXEC = InvalidArgument
+ | errno == eNOLCK = ResourceExhausted
+ | errno == eNOLINK = ResourceVanished
+ | errno == eNOMEM = ResourceExhausted
+ | errno == eNOMSG = NoSuchThing
+ | errno == eNONET = NoSuchThing
+ | errno == eNOPROTOOPT = UnsupportedOperation
+ | errno == eNOSPC = ResourceExhausted
+ | errno == eNOSR = ResourceExhausted
+ | errno == eNOSTR = InvalidArgument
+ | errno == eNOSYS = UnsupportedOperation
+ | errno == eNOTBLK = InvalidArgument
+ | errno == eNOTCONN = InvalidArgument
+ | errno == eNOTDIR = InappropriateType
+ | errno == eNOTEMPTY = UnsatisfiedConstraints
+ | errno == eNOTSOCK = InvalidArgument
+ | errno == eNOTTY = IllegalOperation
+ | errno == eNXIO = NoSuchThing
+ | errno == eOPNOTSUPP = UnsupportedOperation
+ | errno == ePERM = PermissionDenied
+ | errno == ePFNOSUPPORT = UnsupportedOperation
+ | errno == ePIPE = ResourceVanished
+ | errno == ePROCLIM = PermissionDenied
+ | errno == ePROCUNAVAIL = UnsupportedOperation
+ | errno == ePROGMISMATCH = ProtocolError
+ | errno == ePROGUNAVAIL = UnsupportedOperation
+ | errno == ePROTO = ProtocolError
+ | errno == ePROTONOSUPPORT = ProtocolError
+ | errno == ePROTOTYPE = ProtocolError
+ | errno == eRANGE = UnsupportedOperation
+ | errno == eREMCHG = ResourceVanished
+ | errno == eREMOTE = IllegalOperation
+ | errno == eROFS = PermissionDenied
+ | errno == eRPCMISMATCH = ProtocolError
+ | errno == eRREMOTE = IllegalOperation
+ | errno == eSHUTDOWN = IllegalOperation
+ | errno == eSOCKTNOSUPPORT = UnsupportedOperation
+ | errno == eSPIPE = UnsupportedOperation
+ | errno == eSRCH = NoSuchThing
+ | errno == eSRMNT = UnsatisfiedConstraints
+ | errno == eSTALE = ResourceVanished
+ | errno == eTIME = TimeExpired
+ | errno == eTIMEDOUT = TimeExpired
+ | errno == eTOOMANYREFS = ResourceExhausted
+ | errno == eTXTBSY = ResourceBusy
+ | errno == eUSERS = ResourceExhausted
+ | errno == eWOULDBLOCK = OtherError
+ | errno == eXDEV = UnsupportedOperation
+ | otherwise = OtherError
+#else
+ return (userError (loc ++ ": " ++ str ++ maybe "" (": "++) maybeName))
+#endif
+
+foreign import unsafe strerror :: Errno -> IO (Ptr CChar)
diff --git a/libraries/base/Foreign/C/String.hs b/libraries/base/Foreign/C/String.hs
new file mode 100644
index 0000000000..eddf5ab7d7
--- /dev/null
+++ b/libraries/base/Foreign/C/String.hs
@@ -0,0 +1,179 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.C.String
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: String.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Utilities for primitive marshaling
+--
+-----------------------------------------------------------------------------
+
+module Foreign.C.String ( -- representation of strings in C
+
+ CString, -- = Ptr CChar
+ CStringLen, -- = (CString, Int)
+
+ -- conversion of C strings into Haskell strings
+ --
+ peekCString, -- :: CString -> IO String
+ peekCStringLen, -- :: CStringLen -> IO String
+
+ -- conversion of Haskell strings into C strings
+ --
+ newCString, -- :: String -> IO CString
+ newCStringLen, -- :: String -> IO CStringLen
+
+ -- conversion of Haskell strings into C strings using temporary storage
+ --
+ withCString, -- :: String -> (CString -> IO a) -> IO a
+ withCStringLen, -- :: String -> (CStringLen -> IO a) -> IO a
+
+ -- conversion between Haskell and C characters *ignoring* the encoding
+ --
+ castCharToCChar, -- :: Char -> CChar
+ castCCharToChar, -- :: CChar -> Char
+
+ -- UnsafeCString: these might be more efficient than CStrings when
+ -- passing the string to an "unsafe" foreign import. NOTE: this
+ -- feature might be removed in favour of a more general approach in
+ -- the future.
+ --
+ UnsafeCString, -- abstract
+ withUnsafeCString, -- :: String -> (UnsafeCString -> IO a) -> IO a
+
+ ) where
+
+import Foreign.Marshal.Array
+import Foreign.C.Types
+import Foreign.Ptr
+
+import Data.Word
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.ByteArr
+import GHC.Pack
+import GHC.List
+import GHC.Real
+import GHC.Num
+import GHC.IOBase
+import GHC.Base
+#endif
+
+-----------------------------------------------------------------------------
+-- Strings
+
+-- representation of strings in C
+-- ------------------------------
+
+type CString = Ptr CChar -- conventional NUL terminates strings
+type CStringLen = (CString, Int) -- strings with explicit length
+
+
+-- exported functions
+-- ------------------
+--
+-- * the following routines apply the default conversion when converting the
+-- C-land character encoding into the Haskell-land character encoding
+--
+-- ** NOTE: The current implementation doesn't handle conversions yet! **
+--
+-- * the routines using an explicit length tolerate NUL characters in the
+-- middle of a string
+--
+
+-- marshal a NUL terminated C string into a Haskell string
+--
+peekCString :: CString -> IO String
+peekCString cp = do cs <- peekArray0 nUL cp; return (cCharsToChars cs)
+
+-- marshal a C string with explicit length into a Haskell string
+--
+peekCStringLen :: CStringLen -> IO String
+peekCStringLen (cp, len) = do cs <- peekArray len cp; return (cCharsToChars cs)
+
+-- marshal a Haskell string into a NUL terminated C strings
+--
+-- * the Haskell string may *not* contain any NUL characters
+--
+-- * new storage is allocated for the C string and must be explicitly freed
+--
+newCString :: String -> IO CString
+newCString = newArray0 nUL . charsToCChars
+
+-- marshal a Haskell string into a C string (ie, character array) with
+-- explicit length information
+--
+-- * new storage is allocated for the C string and must be explicitly freed
+--
+newCStringLen :: String -> IO CStringLen
+newCStringLen str = do a <- newArray (charsToCChars str)
+ return (pairLength str a)
+
+-- marshal a Haskell string into a NUL terminated C strings using temporary
+-- storage
+--
+-- * the Haskell string may *not* contain any NUL characters
+--
+-- * see the lifetime constraints of `MarshalAlloc.alloca'
+--
+withCString :: String -> (CString -> IO a) -> IO a
+withCString = withArray0 nUL . charsToCChars
+
+-- marshal a Haskell string into a NUL terminated C strings using temporary
+-- storage
+--
+-- * the Haskell string may *not* contain any NUL characters
+--
+-- * see the lifetime constraints of `MarshalAlloc.alloca'
+--
+withCStringLen :: String -> (CStringLen -> IO a) -> IO a
+withCStringLen str act = withArray (charsToCChars str) $ act . pairLength str
+
+-- auxilliary definitions
+-- ----------------------
+
+-- C's end of string character
+--
+nUL :: CChar
+nUL = 0
+
+-- pair a C string with the length of the given Haskell string
+--
+pairLength :: String -> CString -> CStringLen
+pairLength = flip (,) . length
+
+-- cast [CChar] to [Char]
+--
+cCharsToChars :: [CChar] -> [Char]
+cCharsToChars = map castCCharToChar
+
+-- cast [Char] to [CChar]
+--
+charsToCChars :: [Char] -> [CChar]
+charsToCChars = map castCharToCChar
+
+castCCharToChar :: CChar -> Char
+castCCharToChar ch = unsafeChr (fromIntegral (fromIntegral ch :: Word8))
+
+castCharToCChar :: Char -> CChar
+castCharToCChar ch = fromIntegral (ord ch)
+
+
+-- unsafe CStrings
+-- ---------------
+
+withUnsafeCString :: String -> (UnsafeCString -> IO a) -> IO a
+#if __GLASGOW_HASKELL__
+newtype UnsafeCString = UnsafeCString (ByteArray Int)
+withUnsafeCString s f = f (UnsafeCString (packString s))
+#else
+newtype UnsafeCString = UnsafeCString (Ptr CChar)
+withUnsafeCString s f = withCString s (\p -> f (UnsafeCString p))
+#endif
diff --git a/libraries/base/Foreign/C/Types.hs b/libraries/base/Foreign/C/Types.hs
new file mode 100644
index 0000000000..f20967299d
--- /dev/null
+++ b/libraries/base/Foreign/C/Types.hs
@@ -0,0 +1,114 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.C.Types
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Types.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Mapping of C types to corresponding Haskell types. A cool hack...
+--
+-----------------------------------------------------------------------------
+
+module Foreign.C.Types
+ ( -- Integral types, instances of: Eq, Ord, Num, Read, Show, Enum,
+ -- Typeable, Storable, Bounded, Real, Integral, Bits
+ CChar(..), CSChar(..), CUChar(..)
+ , CShort(..), CUShort(..), CInt(..), CUInt(..)
+ , CLong(..), CULong(..), CLLong(..), CULLong(..)
+
+ -- Floating types, instances of: Eq, Ord, Num, Read, Show, Enum,
+ -- Typeable, Storable, Real, Fractional, Floating, RealFrac, RealFloat
+ , CFloat(..), CDouble(..), CLDouble(..)
+ ) where
+
+import Data.Bits ( Bits(..) )
+import Data.Int ( Int8, Int16, Int32, Int64 )
+import Data.Word ( Word8, Word16, Word32, Word64 )
+import Data.Dynamic
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.Float
+import GHC.Enum
+import GHC.Real
+import GHC.Show
+import GHC.Read
+import GHC.Num
+#endif
+
+#include "CTypes.h"
+
+INTEGRAL_TYPE(CChar,tyConCChar,"CChar",HTYPE_CHAR)
+INTEGRAL_TYPE(CSChar,tyConCSChar,"CSChar",HTYPE_SIGNED_CHAR)
+INTEGRAL_TYPE(CUChar,tyConCUChar,"CUChar",HTYPE_UNSIGNED_CHAR)
+
+INTEGRAL_TYPE(CShort,tyConCShort,"CShort",HTYPE_SHORT)
+INTEGRAL_TYPE(CUShort,tyConCUShort,"CUShort",HTYPE_UNSIGNED_SHORT)
+
+INTEGRAL_TYPE(CInt,tyConCInt,"CInt",HTYPE_INT)
+INTEGRAL_TYPE(CUInt,tyConCUInt,"CUInt",HTYPE_UNSIGNED_INT)
+
+INTEGRAL_TYPE(CLong,tyConCLong,"CLong",HTYPE_LONG)
+INTEGRAL_TYPE(CULong,tyConCULong,"CULong",HTYPE_UNSIGNED_LONG)
+
+INTEGRAL_TYPE(CLLong,tyConCLLong,"CLLong",HTYPE_LONG_LONG)
+INTEGRAL_TYPE(CULLong,tyConCULLong,"CULLong",HTYPE_UNSIGNED_LONG_LONG)
+
+{-# RULES
+"fromIntegral/a->CChar" fromIntegral = \x -> CChar (fromIntegral x)
+"fromIntegral/a->CSChar" fromIntegral = \x -> CSChar (fromIntegral x)
+"fromIntegral/a->CUChar" fromIntegral = \x -> CUChar (fromIntegral x)
+"fromIntegral/a->CShort" fromIntegral = \x -> CShort (fromIntegral x)
+"fromIntegral/a->CUShort" fromIntegral = \x -> CUShort (fromIntegral x)
+"fromIntegral/a->CInt" fromIntegral = \x -> CInt (fromIntegral x)
+"fromIntegral/a->CUInt" fromIntegral = \x -> CUInt (fromIntegral x)
+"fromIntegral/a->CLong" fromIntegral = \x -> CLong (fromIntegral x)
+"fromIntegral/a->CULong" fromIntegral = \x -> CULong (fromIntegral x)
+"fromIntegral/a->CLLong" fromIntegral = \x -> CLLong (fromIntegral x)
+"fromIntegral/a->CULLong" fromIntegral = \x -> CULLong (fromIntegral x)
+
+"fromIntegral/CChar->a" fromIntegral = \(CChar x) -> fromIntegral x
+"fromIntegral/CSChar->a" fromIntegral = \(CSChar x) -> fromIntegral x
+"fromIntegral/CUChar->a" fromIntegral = \(CUChar x) -> fromIntegral x
+"fromIntegral/CShort->a" fromIntegral = \(CShort x) -> fromIntegral x
+"fromIntegral/CUShort->a" fromIntegral = \(CUShort x) -> fromIntegral x
+"fromIntegral/CInt->a" fromIntegral = \(CInt x) -> fromIntegral x
+"fromIntegral/CUInt->a" fromIntegral = \(CUInt x) -> fromIntegral x
+"fromIntegral/CLong->a" fromIntegral = \(CLong x) -> fromIntegral x
+"fromIntegral/CULong->a" fromIntegral = \(CULong x) -> fromIntegral x
+"fromIntegral/CLLong->a" fromIntegral = \(CLLong x) -> fromIntegral x
+"fromIntegral/CULLong->a" fromIntegral = \(CULLong x) -> fromIntegral x
+ #-}
+
+FLOATING_TYPE(CFloat,tyConCFloat,"CFloat",HTYPE_FLOAT)
+FLOATING_TYPE(CDouble,tyConCDouble,"CDouble",HTYPE_DOUBLE)
+-- HACK: Currently no long double in the FFI, so we simply re-use double
+FLOATING_TYPE(CLDouble,tyConCLDouble,"CLDouble",HTYPE_DOUBLE)
+
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(CChar,cCharTc,"CChar")
+INSTANCE_TYPEABLE0(CSChar,cSCharTc,"CSChar")
+INSTANCE_TYPEABLE0(CUChar,cUCharTc,"CUChar")
+
+INSTANCE_TYPEABLE0(CShort,cShortTc,"CShort")
+INSTANCE_TYPEABLE0(CUShort,cUShortTc,"CUShort")
+
+INSTANCE_TYPEABLE0(CInt,cIntTc,"CInt")
+INSTANCE_TYPEABLE0(CUInt,cUIntTc,"CUInt")
+
+INSTANCE_TYPEABLE0(CLong,cLongTc,"CLong")
+INSTANCE_TYPEABLE0(CULong,cULongTc,"CULong")
+
+INSTANCE_TYPEABLE0(CLLong,cLLongTc,"CLLong")
+INSTANCE_TYPEABLE0(CULLong,cULLongTc,"CULLong")
+
+INSTANCE_TYPEABLE0(CFloat,cFloatTc,"CFloat")
+INSTANCE_TYPEABLE0(CDouble,cDoubleTc,"CDouble")
+INSTANCE_TYPEABLE0(CLDouble,cLDoubleTc,"CLDouble")
diff --git a/libraries/base/Foreign/C/TypesISO.hs b/libraries/base/Foreign/C/TypesISO.hs
new file mode 100644
index 0000000000..3d971f1e72
--- /dev/null
+++ b/libraries/base/Foreign/C/TypesISO.hs
@@ -0,0 +1,84 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.C.TypesISO
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: TypesISO.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- A mapping of C types defined by the ISO C standard to corresponding Haskell
+-- types. Like CTypes, this is a cool hack...
+--
+-----------------------------------------------------------------------------
+
+module Foreign.C.TypesISO
+ ( -- Integral types, instances of: Eq, Ord, Num, Read, Show, Enum,
+ -- Typeable, Storable, Bounded, Real, Integral, Bits
+ CPtrdiff(..), CSize(..), CWchar(..), CSigAtomic(..)
+
+ -- Numeric types, instances of: Eq, Ord, Num, Read, Show, Enum,
+ -- Typeable, Storable
+ , CClock(..), CTime(..),
+
+ , CFile, CFpos, CJmpBuf
+ ) where
+
+import Data.Bits ( Bits(..) )
+import Data.Int
+import Data.Word
+import Data.Dynamic
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.Enum
+import GHC.Real
+import GHC.Show
+import GHC.Read
+import GHC.Num
+#endif
+
+#include "CTypes.h"
+
+INTEGRAL_TYPE(CPtrdiff,tyConCPtrdiff,"CPtrdiff",HTYPE_PTRDIFF_T)
+INTEGRAL_TYPE(CSize,tyConCSize,"CSize",HTYPE_SIZE_T)
+INTEGRAL_TYPE(CWchar,tyConCWchar,"CWchar",HTYPE_WCHAR_T)
+INTEGRAL_TYPE(CSigAtomic,tyConCSigAtomic,"CSigAtomic",HTYPE_SIG_ATOMIC_T)
+
+{-# RULES
+"fromIntegral/a->CPtrdiff" fromIntegral = \x -> CPtrdiff (fromIntegral x)
+"fromIntegral/a->CSize" fromIntegral = \x -> CSize (fromIntegral x)
+"fromIntegral/a->CWchar" fromIntegral = \x -> CWchar (fromIntegral x)
+"fromIntegral/a->CSigAtomic" fromIntegral = \x -> CSigAtomic (fromIntegral x)
+
+"fromIntegral/CPtrdiff->a" fromIntegral = \(CPtrdiff x) -> fromIntegral x
+"fromIntegral/CSize->a" fromIntegral = \(CSize x) -> fromIntegral x
+"fromIntegral/CWchar->a" fromIntegral = \(CWchar x) -> fromIntegral x
+"fromIntegral/CSigAtomic->a" fromIntegral = \(CSigAtomic x) -> fromIntegral x
+ #-}
+
+INTEGRAL_TYPE(CClock,tyConCClock,"CClock",HTYPE_CLOCK_T)
+INTEGRAL_TYPE(CTime,tyConCTime,"CTime",HTYPE_TIME_T)
+
+-- TODO: Instances. But which...? :-}
+
+data CFile = CFile
+
+data CFpos = CFpos
+
+data CJmpBuf = CJmpBuf
+
+-- C99 types which are still missing include:
+-- intptr_t, uintptr_t, intmax_t, uintmax_t, wint_t, wctrans_t, wctype_t
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(CPtrdiff,cPtrdiffTc,"CPtrdiff")
+INSTANCE_TYPEABLE0(CSize,cSizeTc,"CSize")
+INSTANCE_TYPEABLE0(CWchar,cWcharTc,"CWchar")
+INSTANCE_TYPEABLE0(CSigAtomic,cSigAtomicTc,"CSigAtomic")
+INSTANCE_TYPEABLE0(CClock,cClockTc,"CClock")
+INSTANCE_TYPEABLE0(CTime,cTimeTc,"CTime")
diff --git a/libraries/base/Foreign/ForeignPtr.hs b/libraries/base/Foreign/ForeignPtr.hs
new file mode 100644
index 0000000000..64313cf76d
--- /dev/null
+++ b/libraries/base/Foreign/ForeignPtr.hs
@@ -0,0 +1,88 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.ForeignPtr
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: ForeignPtr.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- This module defines foreign pointers, i.e. addresses with associated
+-- finalizers.
+--
+-----------------------------------------------------------------------------
+
+module Foreign.ForeignPtr
+ ( ForeignPtr, -- abstract, instance of: Eq
+ , newForeignPtr -- :: Ptr a -> IO () -> IO (ForeignPtr a)
+ , addForeignPtrFinalizer -- :: ForeignPtr a -> IO () -> IO ()
+ , withForeignPtr -- :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
+ , foreignPtrToPtr -- :: ForeignPtr a -> Ptr a
+ , touchForeignPtr -- :: ForeignPtr a -> IO ()
+ , castForeignPtr -- :: ForeignPtr a -> ForeignPtr b
+ )
+ where
+
+import Foreign.Ptr
+import Data.Dynamic
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.IOBase
+import GHC.Num
+import GHC.Err
+#endif
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr")
+
+#ifdef __GLASGOW_HASKELL__
+data ForeignPtr a = ForeignPtr ForeignObj#
+instance CCallable (ForeignPtr a)
+
+eqForeignPtr :: ForeignPtr a -> ForeignPtr a -> Bool
+eqForeignPtr mp1 mp2
+ = unsafePerformIO (primEqForeignPtr mp1 mp2) /= (0::Int)
+
+foreign import "eqForeignObj" unsafe
+ primEqForeignPtr :: ForeignPtr a -> ForeignPtr a -> IO Int
+
+instance Eq (ForeignPtr a) where
+ p == q = eqForeignPtr p q
+ p /= q = not (eqForeignPtr p q)
+
+newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)
+newForeignPtr p finalizer
+ = do fObj <- mkForeignPtr p
+ addForeignPtrFinalizer fObj finalizer
+ return fObj
+
+addForeignPtrFinalizer :: ForeignPtr a -> IO () -> IO ()
+addForeignPtrFinalizer (ForeignPtr fo) finalizer =
+ IO $ \s -> case mkWeak# fo () finalizer s of { (# s1, w #) -> (# s1, () #) }
+
+mkForeignPtr :: Ptr a -> IO (ForeignPtr a) {- not exported -}
+mkForeignPtr (Ptr obj) = IO ( \ s# ->
+ case mkForeignObj# obj s# of
+ (# s1#, fo# #) -> (# s1#, ForeignPtr fo# #) )
+
+touchForeignPtr :: ForeignPtr a -> IO ()
+touchForeignPtr (ForeignPtr fo)
+ = IO $ \s -> case touch# fo s of s -> (# s, () #)
+
+withForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
+withForeignPtr fo io
+ = do r <- io (foreignPtrToPtr fo)
+ touchForeignPtr fo
+ return r
+
+foreignPtrToPtr :: ForeignPtr a -> Ptr a
+foreignPtrToPtr (ForeignPtr fo) = Ptr (foreignObjToAddr# fo)
+
+castForeignPtr (ForeignPtr a) = ForeignPtr a
+#endif
+
diff --git a/libraries/base/Foreign/Marshal/Alloc.hs b/libraries/base/Foreign/Marshal/Alloc.hs
new file mode 100644
index 0000000000..ed16c0167d
--- /dev/null
+++ b/libraries/base/Foreign/Marshal/Alloc.hs
@@ -0,0 +1,115 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.Marshal.Alloc
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Alloc.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Marshalling support: basic routines for memory allocation
+--
+-----------------------------------------------------------------------------
+
+module Foreign.Marshal.Alloc (
+ malloc, -- :: Storable a => IO (Ptr a)
+ mallocBytes, -- :: Int -> IO (Ptr a)
+
+ alloca, -- :: Storable a => (Ptr a -> IO b) -> IO b
+ allocaBytes, -- :: Int -> (Ptr a -> IO b) -> IO b
+
+ reallocBytes, -- :: Ptr a -> Int -> IO (Ptr a)
+
+ free -- :: Ptr a -> IO ()
+) where
+
+import Data.Maybe
+import Foreign.Ptr ( Ptr, nullPtr )
+import Foreign.C.TypesISO ( CSize )
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Exception ( bracket )
+import GHC.Storable ( Storable(sizeOf) )
+import GHC.IOBase
+import GHC.Real
+import GHC.Err
+import GHC.Base
+#endif
+
+
+-- exported functions
+-- ------------------
+
+-- allocate space for storable type
+--
+malloc :: Storable a => IO (Ptr a)
+malloc = doMalloc undefined
+ where
+ doMalloc :: Storable a => a -> IO (Ptr a)
+ doMalloc dummy = mallocBytes (sizeOf dummy)
+
+-- allocate given number of bytes of storage
+--
+mallocBytes :: Int -> IO (Ptr a)
+mallocBytes size = failWhenNULL "malloc" (_malloc (fromIntegral size))
+
+-- temporarily allocate space for a storable type
+--
+-- * the pointer passed as an argument to the function must *not* escape from
+-- this function; in other words, in `alloca f' the allocated storage must
+-- not be used after `f' returns
+--
+alloca :: Storable a => (Ptr a -> IO b) -> IO b
+alloca = doAlloca undefined
+ where
+ doAlloca :: Storable a => a -> (Ptr a -> IO b) -> IO b
+ doAlloca dummy = allocaBytes (sizeOf dummy)
+
+-- temporarily allocate the given number of bytes of storage
+--
+-- * the pointer passed as an argument to the function must *not* escape from
+-- this function; in other words, in `allocaBytes n f' the allocated storage
+-- must not be used after `f' returns
+--
+allocaBytes :: Int -> (Ptr a -> IO b) -> IO b
+allocaBytes size = bracket (mallocBytes size) free
+
+-- adjust a malloc'ed storage area to the given size
+--
+reallocBytes :: Ptr a -> Int -> IO (Ptr a)
+reallocBytes ptr size =
+ failWhenNULL "realloc" (_realloc ptr (fromIntegral size))
+
+-- free malloc'ed storage
+--
+free :: Ptr a -> IO ()
+free = _free
+
+
+-- auxilliary routines
+-- -------------------
+
+-- asserts that the pointer returned from the action in the second argument is
+-- non-null
+--
+failWhenNULL :: String -> IO (Ptr a) -> IO (Ptr a)
+failWhenNULL name f = do
+ addr <- f
+ if addr == nullPtr
+#ifdef __GLASGOW_HASKELL__
+ then ioException (IOError Nothing ResourceExhausted name
+ "out of memory" Nothing)
+#else
+ then ioError (userError (name++": out of memory"))
+#endif
+ else return addr
+
+-- basic C routines needed for memory allocation
+--
+foreign import "malloc" unsafe _malloc :: CSize -> IO (Ptr a)
+foreign import "realloc" unsafe _realloc :: Ptr a -> CSize -> IO (Ptr a)
+foreign import "free" unsafe _free :: Ptr a -> IO ()
diff --git a/libraries/base/Foreign/Marshal/Array.hs b/libraries/base/Foreign/Marshal/Array.hs
new file mode 100644
index 0000000000..cddd0585ef
--- /dev/null
+++ b/libraries/base/Foreign/Marshal/Array.hs
@@ -0,0 +1,268 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.Marshal.Array
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Array.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Marshalling support: routines allocating, storing, and retrieving Haskell
+-- lists that are represented as arrays in the foreign language
+--
+-----------------------------------------------------------------------------
+
+module Foreign.Marshal.Array (
+
+ -- allocation
+ --
+ mallocArray, -- :: Storable a => Int -> IO (Ptr a)
+ mallocArray0, -- :: Storable a => Int -> IO (Ptr a)
+
+ allocaArray, -- :: Storable a => Int -> (Ptr a -> IO b) -> IO b
+ allocaArray0, -- :: Storable a => Int -> (Ptr a -> IO b) -> IO b
+
+ reallocArray, -- :: Storable a => Ptr a -> Int -> IO (Ptr a)
+ reallocArray0, -- :: Storable a => Ptr a -> Int -> IO (Ptr a)
+
+ -- marshalling
+ --
+ peekArray, -- :: Storable a => Int -> Ptr a -> IO [a]
+ peekArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO [a]
+
+ pokeArray, -- :: Storable a => Ptr a -> [a] -> IO ()
+ pokeArray0, -- :: Storable a => a -> Ptr a -> [a] -> IO ()
+
+ -- combined allocation and marshalling
+ --
+ newArray, -- :: Storable a => [a] -> IO (Ptr a)
+ newArray0, -- :: Storable a => a -> [a] -> IO (Ptr a)
+
+ withArray, -- :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
+ withArray0, -- :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
+
+ -- destruction
+ --
+ destructArray, -- :: Storable a => Int -> Ptr a -> IO ()
+ destructArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO ()
+
+ -- copying (argument order: destination, source)
+ --
+ copyArray, -- :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
+ moveArray, -- :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
+
+ -- finding the length
+ --
+ lengthArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO Int
+
+ -- indexing
+ --
+ advancePtr -- :: Storable a => Ptr a -> Int -> Ptr a
+) where
+
+import Control.Monad
+
+#ifdef __GLASGOW_HASKELL__
+import Foreign.Ptr (Ptr, plusPtr)
+import GHC.Storable (Storable(sizeOf,peekElemOff,pokeElemOff,destruct))
+import Foreign.Marshal.Alloc (mallocBytes, allocaBytes, reallocBytes)
+import Foreign.Marshal.Utils (copyBytes, moveBytes)
+import GHC.IOBase
+import GHC.Num
+import GHC.List
+import GHC.Err
+import GHC.Base
+#endif
+
+-- allocation
+-- ----------
+
+-- allocate storage for the given number of elements of a storable type
+--
+mallocArray :: Storable a => Int -> IO (Ptr a)
+mallocArray = doMalloc undefined
+ where
+ doMalloc :: Storable a => a -> Int -> IO (Ptr a)
+ doMalloc dummy size = mallocBytes (size * sizeOf dummy)
+
+-- like `mallocArray', but add an extra element to signal the end of the array
+--
+mallocArray0 :: Storable a => Int -> IO (Ptr a)
+mallocArray0 size = mallocArray (size + 1)
+
+-- temporarily allocate space for the given number of elements
+--
+-- * see `MarshalAlloc.alloca' for the storage lifetime constraints
+--
+allocaArray :: Storable a => Int -> (Ptr a -> IO b) -> IO b
+allocaArray = doAlloca undefined
+ where
+ doAlloca :: Storable a => a -> Int -> (Ptr a -> IO b) -> IO b
+ doAlloca dummy size = allocaBytes (size * sizeOf dummy)
+
+-- like `allocaArray', but add an extra element to signal the end of the array
+--
+allocaArray0 :: Storable a => Int -> (Ptr a -> IO b) -> IO b
+allocaArray0 size = allocaArray (size + 1)
+
+-- adjust the size of an array
+--
+reallocArray :: Storable a => Ptr a -> Int -> IO (Ptr a)
+reallocArray = doRealloc undefined
+ where
+ doRealloc :: Storable a => a -> Ptr a -> Int -> IO (Ptr a)
+ doRealloc dummy ptr size = reallocBytes ptr (size * sizeOf dummy)
+
+-- adjust the size of an array while adding an element for the end marker
+--
+reallocArray0 :: Storable a => Ptr a -> Int -> IO (Ptr a)
+reallocArray0 ptr size = reallocArray ptr (size + 1)
+
+
+-- marshalling
+-- -----------
+
+-- convert an array of given length into a Haskell list
+--
+peekArray :: Storable a => Int -> Ptr a -> IO [a]
+peekArray size ptr = mapM (peekElemOff ptr) [0..size-1]
+
+-- convert an array terminated by the given end marker into a Haskell list
+--
+peekArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO [a]
+peekArray0 marker ptr = loop 0
+ where
+ loop i = do
+ val <- peekElemOff ptr i
+ if val == marker then return [] else do
+ rest <- loop (i+1)
+ return (val:rest)
+
+-- write the list elements consecutive into memory
+--
+pokeArray :: Storable a => Ptr a -> [a] -> IO ()
+pokeArray ptr vals = zipWithM_ (pokeElemOff ptr) [0..] vals
+
+-- write the list elements consecutive into memory and terminate them with the
+-- given marker element
+--
+pokeArray0 :: Storable a => a -> Ptr a -> [a] -> IO ()
+pokeArray0 marker ptr vals = do
+ pokeArray ptr vals
+ pokeElemOff ptr (length vals) marker
+
+
+-- combined allocation and marshalling
+-- -----------------------------------
+
+-- write a list of storable elements into a newly allocated, consecutive
+-- sequence of storable values
+--
+newArray :: Storable a => [a] -> IO (Ptr a)
+newArray vals = do
+ ptr <- mallocArray (length vals)
+ pokeArray ptr vals
+ return ptr
+
+-- write a list of storable elements into a newly allocated, consecutive
+-- sequence of storable values, where the end is fixed by the given end marker
+--
+newArray0 :: Storable a => a -> [a] -> IO (Ptr a)
+newArray0 marker vals = do
+ ptr <- mallocArray0 (length vals)
+ pokeArray0 marker ptr vals
+ return ptr
+
+-- temporarily store a list of storable values in memory
+--
+withArray :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
+withArray vals f =
+ allocaArray len $ \ptr -> do
+ pokeArray ptr vals
+ res <- f ptr
+ destructArray len ptr
+ return res
+ where
+ len = length vals
+
+-- like `withArray', but a terminator indicates where the array ends
+--
+withArray0 :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
+withArray0 marker vals f =
+ allocaArray0 len $ \ptr -> do
+ pokeArray0 marker ptr vals
+ res <- f ptr
+ destructArray (len+1) ptr
+ return res
+ where
+ len = length vals
+
+
+-- destruction
+-- -----------
+
+-- destruct each element of an array (in reverse order)
+--
+destructArray :: Storable a => Int -> Ptr a -> IO ()
+destructArray size ptr =
+ sequence_ [destruct (ptr `advancePtr` i)
+ | i <- [size-1, size-2 .. 0]]
+
+-- like `destructArray', but a terminator indicates where the array ends
+--
+destructArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO ()
+destructArray0 marker ptr = do
+ size <- lengthArray0 marker ptr
+ sequence_ [destruct (ptr `advancePtr` i)
+ | i <- [size, size-1 .. 0]]
+
+
+-- copying (argument order: destination, source)
+-- -------
+
+-- copy the given number of elements from the second array (source) into the
+-- first array (destination); the copied areas may *not* overlap
+--
+copyArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
+copyArray = doCopy undefined
+ where
+ doCopy :: Storable a => a -> Ptr a -> Ptr a -> Int -> IO ()
+ doCopy dummy dest src size = copyBytes dest src (size * sizeOf dummy)
+
+-- copy the given number of elements from the second array (source) into the
+-- first array (destination); the copied areas *may* overlap
+--
+moveArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
+moveArray = doMove undefined
+ where
+ doMove :: Storable a => a -> Ptr a -> Ptr a -> Int -> IO ()
+ doMove dummy dest src size = moveBytes dest src (size * sizeOf dummy)
+
+
+-- finding the length
+-- ------------------
+
+-- return the number of elements in an array, excluding the terminator
+--
+lengthArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO Int
+lengthArray0 marker ptr = loop 0
+ where
+ loop i = do
+ val <- peekElemOff ptr i
+ if val == marker then return i else loop (i+1)
+
+
+-- indexing
+-- --------
+
+-- advance a pointer into an array by the given number of elements
+--
+advancePtr :: Storable a => Ptr a -> Int -> Ptr a
+advancePtr = doAdvance undefined
+ where
+ doAdvance :: Storable a => a -> Ptr a -> Int -> Ptr a
+ doAdvance dummy ptr i = ptr `plusPtr` (i * sizeOf dummy)
diff --git a/libraries/base/Foreign/Marshal/Error.hs b/libraries/base/Foreign/Marshal/Error.hs
new file mode 100644
index 0000000000..c896ce24bc
--- /dev/null
+++ b/libraries/base/Foreign/Marshal/Error.hs
@@ -0,0 +1,81 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.Marshal.Error
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Error.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Marshalling support: Handling of common error conditions
+--
+-----------------------------------------------------------------------------
+
+module Foreign.Marshal.Error (
+
+ -- throw an exception on specific return values
+ --
+ throwIf, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO a
+ throwIf_, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO ()
+ throwIfNeg, -- :: (Ord a, Num a)
+ -- => (a -> String) -> IO a -> IO a
+ throwIfNeg_, -- :: (Ord a, Num a)
+ -- => (a -> String) -> IO a -> IO ()
+ throwIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)
+
+ -- discard return value
+ --
+ void -- IO a -> IO ()
+) where
+
+import Foreign.Ptr
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.Num
+import GHC.IOBase
+#endif
+
+-- exported functions
+-- ------------------
+
+-- guard an IO operation and throw an exception if the result meets the given
+-- predicate
+--
+-- * the second argument computes an error message from the result of the IO
+-- operation
+--
+throwIf :: (a -> Bool) -> (a -> String) -> IO a -> IO a
+throwIf pred msgfct act =
+ do
+ res <- act
+ (if pred res then ioError . userError . msgfct else return) res
+
+-- like `throwIf', but discarding the result
+--
+throwIf_ :: (a -> Bool) -> (a -> String) -> IO a -> IO ()
+throwIf_ pred msgfct act = void $ throwIf pred msgfct act
+
+-- guards against negative result values
+--
+throwIfNeg :: (Ord a, Num a) => (a -> String) -> IO a -> IO a
+throwIfNeg = throwIf (< 0)
+
+-- like `throwIfNeg', but discarding the result
+--
+throwIfNeg_ :: (Ord a, Num a) => (a -> String) -> IO a -> IO ()
+throwIfNeg_ = throwIf_ (< 0)
+
+-- guards against null pointers
+--
+throwIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
+throwIfNull = throwIf (== nullPtr) . const
+
+-- discard the return value of an IO action
+--
+void :: IO a -> IO ()
+void act = act >> return ()
diff --git a/libraries/base/Foreign/Marshal/Utils.hs b/libraries/base/Foreign/Marshal/Utils.hs
new file mode 100644
index 0000000000..3ae9e066da
--- /dev/null
+++ b/libraries/base/Foreign/Marshal/Utils.hs
@@ -0,0 +1,168 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.Marshal.Utils
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Utils.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Utilities for primitive marshaling
+--
+-----------------------------------------------------------------------------
+
+module Foreign.Marshal.Utils (
+
+ -- combined allocation and marshalling
+ --
+ withObject, -- :: Storable a => a -> (Ptr a -> IO b) -> IO b
+ {- FIXME: should be `with' -}
+ new, -- :: Storable a => a -> IO (Ptr a)
+
+ -- marshalling of Boolean values (non-zero corresponds to `True')
+ --
+ fromBool, -- :: Num a => Bool -> a
+ toBool, -- :: Num a => a -> Bool
+
+ -- marshalling of Maybe values
+ --
+ maybeNew, -- :: ( a -> IO (Ptr a))
+ -- -> (Maybe a -> IO (Ptr a))
+ maybeWith, -- :: ( a -> (Ptr b -> IO c) -> IO c)
+ -- -> (Maybe a -> (Ptr b -> IO c) -> IO c)
+ maybePeek, -- :: (Ptr a -> IO b )
+ -- -> (Ptr a -> IO (Maybe b))
+
+ -- marshalling lists of storable objects
+ --
+ withMany, -- :: (a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
+
+ -- Haskellish interface to memcpy and memmove
+ -- (argument order: destination, source)
+ --
+ copyBytes, -- :: Ptr a -> Ptr a -> Int -> IO ()
+ moveBytes -- :: Ptr a -> Ptr a -> Int -> IO ()
+) where
+
+import Data.Maybe
+
+#ifdef __GLASGOW_HASKELL__
+import Foreign.Ptr ( Ptr, nullPtr )
+import GHC.Storable ( Storable(poke,destruct) )
+import Foreign.C.TypesISO ( CSize )
+import Foreign.Marshal.Alloc ( malloc, alloca )
+import GHC.IOBase
+import GHC.Real ( fromIntegral )
+import GHC.Num
+import GHC.Base
+#endif
+
+-- combined allocation and marshalling
+-- -----------------------------------
+
+-- allocate storage for a value and marshal it into this storage
+--
+new :: Storable a => a -> IO (Ptr a)
+new val =
+ do
+ ptr <- malloc
+ poke ptr val
+ return ptr
+
+-- allocate temporary storage for a value and marshal it into this storage
+--
+-- * see the life time constraints imposed by `alloca'
+--
+{- FIXME: should be called `with' -}
+withObject :: Storable a => a -> (Ptr a -> IO b) -> IO b
+withObject val f =
+ alloca $ \ptr -> do
+ poke ptr val
+ res <- f ptr
+ destruct ptr
+ return res
+
+
+-- marshalling of Boolean values (non-zero corresponds to `True')
+-- -----------------------------
+
+-- convert a Haskell Boolean to its numeric representation
+--
+fromBool :: Num a => Bool -> a
+fromBool False = 0
+fromBool True = 1
+
+-- convert a Boolean in numeric representation to a Haskell value
+--
+toBool :: Num a => a -> Bool
+toBool = (/= 0)
+
+
+-- marshalling of Maybe values
+-- ---------------------------
+
+-- allocate storage and marshall a storable value wrapped into a `Maybe'
+--
+-- * the `nullPtr' is used to represent `Nothing'
+--
+maybeNew :: ( a -> IO (Ptr a))
+ -> (Maybe a -> IO (Ptr a))
+maybeNew = maybe (return nullPtr)
+
+-- converts a withXXX combinator into one marshalling a value wrapped into a
+-- `Maybe'
+--
+maybeWith :: ( a -> (Ptr b -> IO c) -> IO c)
+ -> (Maybe a -> (Ptr b -> IO c) -> IO c)
+maybeWith = maybe ($ nullPtr)
+
+-- convert a peek combinator into a one returning `Nothing' if applied to a
+-- `nullPtr'
+--
+maybePeek :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
+maybePeek peek ptr | ptr == nullPtr = return Nothing
+ | otherwise = do a <- peek ptr; return (Just a)
+
+
+-- marshalling lists of storable objects
+-- -------------------------------------
+
+-- replicates a withXXX combinator over a list of objects, yielding a list of
+-- marshalled objects
+--
+withMany :: (a -> (b -> res) -> res) -- withXXX combinator for one object
+ -> [a] -- storable objects
+ -> ([b] -> res) -- action on list of marshalled obj.s
+ -> res
+withMany _ [] f = f []
+withMany withFoo (x:xs) f = withFoo x $ \x' ->
+ withMany withFoo xs (\xs' -> f (x':xs'))
+
+
+-- Haskellish interface to memcpy and memmove
+-- ------------------------------------------
+
+-- copies the given number of bytes from the second area (source) into the
+-- first (destination); the copied areas may *not* overlap
+--
+copyBytes :: Ptr a -> Ptr a -> Int -> IO ()
+copyBytes dest src size = memcpy dest src (fromIntegral size)
+
+-- copies the given number of elements from the second area (source) into the
+-- first (destination); the copied areas *may* overlap
+--
+moveBytes :: Ptr a -> Ptr a -> Int -> IO ()
+moveBytes dest src size = memmove dest src (fromIntegral size)
+
+
+-- auxilliary routines
+-- -------------------
+
+-- basic C routines needed for memory copying
+--
+foreign import unsafe memcpy :: Ptr a -> Ptr a -> CSize -> IO ()
+foreign import unsafe memmove :: Ptr a -> Ptr a -> CSize -> IO ()
diff --git a/libraries/base/Foreign/Ptr.hs b/libraries/base/Foreign/Ptr.hs
new file mode 100644
index 0000000000..d7f9cb0cde
--- /dev/null
+++ b/libraries/base/Foreign/Ptr.hs
@@ -0,0 +1,55 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.Ptr
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Ptr.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Pointer types.
+--
+-----------------------------------------------------------------------------
+
+module Foreign.Ptr (
+ --------------------------------------------------------------------
+ -- Data pointers.
+
+ Ptr(..), -- data Ptr a
+ nullPtr, -- :: Ptr a
+ castPtr, -- :: Ptr a -> Ptr b
+ plusPtr, -- :: Ptr a -> Int -> Ptr b
+ alignPtr, -- :: Ptr a -> Int -> Ptr a
+ minusPtr, -- :: Ptr a -> Ptr b -> Int
+
+ --------------------------------------------------------------------
+ -- Function pointers.
+
+ FunPtr(..), -- data FunPtr a
+ nullFunPtr, -- :: FunPtr a
+ castFunPtr, -- :: FunPtr a -> FunPtr b
+ castFunPtrToPtr, -- :: FunPtr a -> Ptr b
+ castPtrToFunPtr, -- :: Ptr a -> FunPtr b
+
+ freeHaskellFunPtr, -- :: FunPtr a -> IO ()
+ -- Free the function pointer created by foreign export dynamic.
+
+ ) where
+
+import Data.Dynamic
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Ptr
+import GHC.IOBase
+import GHC.Err
+#endif
+
+foreign import "freeHaskellFunctionPtr" unsafe
+ freeHaskellFunPtr :: FunPtr a -> IO ()
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE1(Ptr,ptrTc,"Ptr")
diff --git a/libraries/base/Foreign/StablePtr.hs b/libraries/base/Foreign/StablePtr.hs
new file mode 100644
index 0000000000..5b94104432
--- /dev/null
+++ b/libraries/base/Foreign/StablePtr.hs
@@ -0,0 +1,35 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.StablePtr
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: StablePtr.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- Stable pointers.
+--
+-----------------------------------------------------------------------------
+
+module Foreign.StablePtr
+ ( StablePtr, -- abstract
+ , newStablePtr -- :: a -> IO (StablePtr a)
+ , deRefStablePtr -- :: StablePtr a -> IO a
+ , freeStablePtr -- :: StablePtr a -> IO ()
+ , castStablePtrToPtr -- :: StablePtr a -> Ptr ()
+ , castPtrToStablePtr -- :: Ptr () -> StablePtr a
+ ) where
+
+import Data.Dynamic
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Stable
+import GHC.Err
+#endif
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE1(StablePtr,stablePtrTc,"StablePtr")
diff --git a/libraries/base/Foreign/Storable.hs b/libraries/base/Foreign/Storable.hs
new file mode 100644
index 0000000000..118a1a35f8
--- /dev/null
+++ b/libraries/base/Foreign/Storable.hs
@@ -0,0 +1,33 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Foreign.Storable
+-- Copyright : (c) The FFI task force 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : ffi@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Storable.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- A class for primitive marshaling
+--
+-----------------------------------------------------------------------------
+
+module Foreign.Storable
+ ( Storable(
+ sizeOf, -- :: a -> Int
+ alignment, -- :: a -> Int
+ peekElemOff, -- :: Ptr a -> Int -> IO a
+ pokeElemOff, -- :: Ptr a -> Int -> a -> IO ()
+ peekByteOff, -- :: Ptr b -> Int -> IO a
+ pokeByteOff, -- :: Ptr b -> Int -> a -> IO ()
+ peek, -- :: Ptr a -> IO a
+ poke, -- :: Ptr a -> a -> IO ()
+ destruct) -- :: Ptr a -> IO ()
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Storable
+#endif
diff --git a/libraries/base/GHC/Arr.lhs b/libraries/base/GHC/Arr.lhs
new file mode 100644
index 0000000000..940b60334f
--- /dev/null
+++ b/libraries/base/GHC/Arr.lhs
@@ -0,0 +1,574 @@
+% -----------------------------------------------------------------------------
+% $Id: Arr.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Arr]{Module @GHC.Arr@}
+
+Array implementation, @GHC.Arr@ exports the basic array
+types and operations.
+
+For byte-arrays see @GHC.ByteArr@.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Arr where
+
+import {-# SOURCE #-} GHC.Err ( error )
+import GHC.Enum
+import GHC.Num
+import GHC.ST
+import GHC.Base
+import GHC.List
+import GHC.Show
+
+infixl 9 !, //
+
+default ()
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @Ix@ class}
+%* *
+%*********************************************************
+
+\begin{code}
+class (Ord a) => Ix a where
+ range :: (a,a) -> [a]
+ index, unsafeIndex :: (a,a) -> a -> Int
+ inRange :: (a,a) -> a -> Bool
+
+ -- Must specify one of index, unsafeIndex
+ index b i | inRange b i = unsafeIndex b i
+ | otherwise = error "Error in array index"
+ unsafeIndex b i = index b i
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Instances of @Ix@}
+%* *
+%*********************************************************
+
+\begin{code}
+-- abstract these errors from the relevant index functions so that
+-- the guts of the function will be small enough to inline.
+
+{-# NOINLINE indexError #-}
+indexError :: Show a => (a,a) -> a -> String -> b
+indexError rng i tp
+ = error (showString "Ix{" . showString tp . showString "}.index: Index " .
+ showParen True (showsPrec 0 i) .
+ showString " out of range " $
+ showParen True (showsPrec 0 rng) "")
+
+----------------------------------------------------------------------
+instance Ix Char where
+ {-# INLINE range #-}
+ range (m,n) = [m..n]
+
+ {-# INLINE unsafeIndex #-}
+ unsafeIndex (m,_n) i = fromEnum i - fromEnum m
+
+ index b i | inRange b i = unsafeIndex b i
+ | otherwise = indexError b i "Char"
+
+ inRange (m,n) i = m <= i && i <= n
+
+----------------------------------------------------------------------
+instance Ix Int where
+ {-# INLINE range #-}
+ -- The INLINE stops the build in the RHS from getting inlined,
+ -- so that callers can fuse with the result of range
+ range (m,n) = [m..n]
+
+ {-# INLINE unsafeIndex #-}
+ unsafeIndex (m,_n) i = i - m
+
+ index b i | inRange b i = unsafeIndex b i
+ | otherwise = indexError b i "Int"
+
+ {-# INLINE inRange #-}
+ inRange (I# m,I# n) (I# i) = m <=# i && i <=# n
+
+----------------------------------------------------------------------
+instance Ix Integer where
+ {-# INLINE range #-}
+ range (m,n) = [m..n]
+
+ {-# INLINE unsafeIndex #-}
+ unsafeIndex (m,_n) i = fromInteger (i - m)
+
+ index b i | inRange b i = unsafeIndex b i
+ | otherwise = indexError b i "Integer"
+
+ inRange (m,n) i = m <= i && i <= n
+
+
+----------------------------------------------------------------------
+instance Ix Bool where -- as derived
+ {-# INLINE range #-}
+ range (m,n) = [m..n]
+
+ {-# INLINE unsafeIndex #-}
+ unsafeIndex (l,_) i = fromEnum i - fromEnum l
+
+ index b i | inRange b i = unsafeIndex b i
+ | otherwise = indexError b i "Bool"
+
+ inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
+
+----------------------------------------------------------------------
+instance Ix Ordering where -- as derived
+ {-# INLINE range #-}
+ range (m,n) = [m..n]
+
+ {-# INLINE unsafeIndex #-}
+ unsafeIndex (l,_) i = fromEnum i - fromEnum l
+
+ index b i | inRange b i = unsafeIndex b i
+ | otherwise = indexError b i "Ordering"
+
+ inRange (l,u) i = fromEnum i >= fromEnum l && fromEnum i <= fromEnum u
+
+----------------------------------------------------------------------
+instance Ix () where
+ {-# INLINE range #-}
+ range ((), ()) = [()]
+ {-# INLINE unsafeIndex #-}
+ unsafeIndex ((), ()) () = 0
+ {-# INLINE inRange #-}
+ inRange ((), ()) () = True
+ {-# INLINE index #-}
+ index b i = unsafeIndex b i
+
+
+----------------------------------------------------------------------
+instance (Ix a, Ix b) => Ix (a, b) where -- as derived
+ {-# SPECIALISE instance Ix (Int,Int) #-}
+
+ {- INLINE range #-}
+ range ((l1,l2),(u1,u2)) =
+ [ (i1,i2) | i1 <- range (l1,u1), i2 <- range (l2,u2) ]
+
+ {- INLINE unsafeIndex #-}
+ unsafeIndex ((l1,l2),(u1,u2)) (i1,i2) =
+ unsafeIndex (l1,u1) i1 * unsafeRangeSize (l2,u2) + unsafeIndex (l2,u2) i2
+
+ {- INLINE inRange #-}
+ inRange ((l1,l2),(u1,u2)) (i1,i2) =
+ inRange (l1,u1) i1 && inRange (l2,u2) i2
+
+ -- Default method for index
+
+----------------------------------------------------------------------
+instance (Ix a1, Ix a2, Ix a3) => Ix (a1,a2,a3) where
+ {-# SPECIALISE instance Ix (Int,Int,Int) #-}
+
+ range ((l1,l2,l3),(u1,u2,u3)) =
+ [(i1,i2,i3) | i1 <- range (l1,u1),
+ i2 <- range (l2,u2),
+ i3 <- range (l3,u3)]
+
+ unsafeIndex ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
+ unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
+ unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
+ unsafeIndex (l1,u1) i1))
+
+ inRange ((l1,l2,l3),(u1,u2,u3)) (i1,i2,i3) =
+ inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
+ inRange (l3,u3) i3
+
+ -- Default method for index
+
+----------------------------------------------------------------------
+instance (Ix a1, Ix a2, Ix a3, Ix a4) => Ix (a1,a2,a3,a4) where
+ range ((l1,l2,l3,l4),(u1,u2,u3,u4)) =
+ [(i1,i2,i3,i4) | i1 <- range (l1,u1),
+ i2 <- range (l2,u2),
+ i3 <- range (l3,u3),
+ i4 <- range (l4,u4)]
+
+ unsafeIndex ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
+ unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
+ unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
+ unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
+ unsafeIndex (l1,u1) i1)))
+
+ inRange ((l1,l2,l3,l4),(u1,u2,u3,u4)) (i1,i2,i3,i4) =
+ inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
+ inRange (l3,u3) i3 && inRange (l4,u4) i4
+
+ -- Default method for index
+
+instance (Ix a1, Ix a2, Ix a3, Ix a4, Ix a5) => Ix (a1,a2,a3,a4,a5) where
+ range ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) =
+ [(i1,i2,i3,i4,i5) | i1 <- range (l1,u1),
+ i2 <- range (l2,u2),
+ i3 <- range (l3,u3),
+ i4 <- range (l4,u4),
+ i5 <- range (l5,u5)]
+
+ unsafeIndex ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
+ unsafeIndex (l5,u5) i5 + unsafeRangeSize (l5,u5) * (
+ unsafeIndex (l4,u4) i4 + unsafeRangeSize (l4,u4) * (
+ unsafeIndex (l3,u3) i3 + unsafeRangeSize (l3,u3) * (
+ unsafeIndex (l2,u2) i2 + unsafeRangeSize (l2,u2) * (
+ unsafeIndex (l1,u1) i1))))
+
+ inRange ((l1,l2,l3,l4,l5),(u1,u2,u3,u4,u5)) (i1,i2,i3,i4,i5) =
+ inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
+ inRange (l3,u3) i3 && inRange (l4,u4) i4 &&
+ inRange (l5,u5) i5
+
+ -- Default method for index
+\end{code}
+
+
+%********************************************************
+%* *
+\subsection{Size of @Ix@ interval}
+%* *
+%********************************************************
+
+The @rangeSize@ operator returns the number of elements
+in the range for an @Ix@ pair.
+
+\begin{code}
+{-# SPECIALISE unsafeRangeSize :: (Int,Int) -> Int #-}
+{-# SPECIALISE unsafeRangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
+unsafeRangeSize :: (Ix a) => (a,a) -> Int
+unsafeRangeSize b@(_l,h) = unsafeIndex b h + 1
+
+{-# SPECIALISE rangeSize :: (Int,Int) -> Int #-}
+{-# SPECIALISE rangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
+rangeSize :: (Ix a) => (a,a) -> Int
+rangeSize b@(_l,h) | inRange b h = unsafeIndex b h + 1
+ | otherwise = 0
+
+-- Note that the following is NOT right
+-- rangeSize (l,h) | l <= h = index b h + 1
+-- | otherwise = 0
+--
+-- Because it might be the case that l<h, but the range
+-- is nevertheless empty. Consider
+-- ((1,2),(2,1))
+-- Here l<h, but the second index ranges from 2..1 and
+-- hence is empty
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{The @Array@ types}
+%* *
+%*********************************************************
+
+\begin{code}
+type IPr = (Int, Int)
+
+data Ix i => Array i e = Array !i !i (Array# e)
+data Ix i => STArray s i e = STArray !i !i (MutableArray# s e)
+
+-- Just pointer equality on mutable arrays:
+instance Eq (STArray s i e) where
+ STArray _ _ arr1# == STArray _ _ arr2# =
+ sameMutableArray# arr1# arr2#
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Operations on immutable arrays}
+%* *
+%*********************************************************
+
+\begin{code}
+{-# NOINLINE arrEleBottom #-}
+arrEleBottom :: a
+arrEleBottom = error "(Array.!): undefined array element"
+
+{-# INLINE array #-}
+array :: Ix i => (i,i) -> [(i, e)] -> Array i e
+array (l,u) ies = unsafeArray (l,u) [(index (l,u) i, e) | (i, e) <- ies]
+
+{-# INLINE unsafeArray #-}
+unsafeArray :: Ix i => (i,i) -> [(Int, e)] -> Array i e
+unsafeArray (l,u) ies = runST (ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newArray# n# arrEleBottom s1# of { (# s2#, marr# #) ->
+ foldr (fill marr#) (done l u marr#) ies s2# }})
+
+{-# INLINE fill #-}
+fill :: MutableArray# s e -> (Int, e) -> STRep s a -> STRep s a
+fill marr# (I# i#, e) next s1# =
+ case writeArray# marr# i# e s1# of { s2# ->
+ next s2# }
+
+{-# INLINE done #-}
+done :: Ix i => i -> i -> MutableArray# s e -> STRep s (Array i e)
+done l u marr# s1# =
+ case unsafeFreezeArray# marr# s1# of { (# s2#, arr# #) ->
+ (# s2#, Array l u arr# #) }
+
+-- This is inefficient and I'm not sure why:
+-- listArray (l,u) es = unsafeArray (l,u) (zip [0 .. rangeSize (l,u) - 1] es)
+-- The code below is better. It still doesn't enable foldr/build
+-- transformation on the list of elements; I guess it's impossible
+-- using mechanisms currently available.
+
+{-# INLINE listArray #-}
+listArray :: Ix i => (i,i) -> [e] -> Array i e
+listArray (l,u) es = runST (ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newArray# n# arrEleBottom s1# of { (# s2#, marr# #) ->
+ let fillFromList i# xs s3# | i# ==# n# = s3#
+ | otherwise = case xs of
+ [] -> s3#
+ y:ys -> case writeArray# marr# i# y s3# of { s4# ->
+ fillFromList (i# +# 1#) ys s4# } in
+ case fillFromList 0# es s2# of { s3# ->
+ done l u marr# s3# }}})
+
+{-# INLINE (!) #-}
+(!) :: Ix i => Array i e -> i -> e
+arr@(Array l u _) ! i = unsafeAt arr (index (l,u) i)
+
+{-# INLINE unsafeAt #-}
+unsafeAt :: Ix i => Array i e -> Int -> e
+unsafeAt (Array _ _ arr#) (I# i#) =
+ case indexArray# arr# i# of (# e #) -> e
+
+{-# INLINE bounds #-}
+bounds :: Ix i => Array i e -> (i,i)
+bounds (Array l u _) = (l,u)
+
+{-# INLINE indices #-}
+indices :: Ix i => Array i e -> [i]
+indices (Array l u _) = range (l,u)
+
+{-# INLINE elems #-}
+elems :: Ix i => Array i e -> [e]
+elems arr@(Array l u _) =
+ [unsafeAt arr i | i <- [0 .. rangeSize (l,u) - 1]]
+
+{-# INLINE assocs #-}
+assocs :: Ix i => Array i e -> [(i, e)]
+assocs arr@(Array l u _) =
+ [(i, unsafeAt arr (unsafeIndex (l,u) i)) | i <- range (l,u)]
+
+{-# INLINE accumArray #-}
+accumArray :: Ix i => (e -> a -> e) -> e -> (i,i) -> [(i, a)] -> Array i e
+accumArray f init (l,u) ies =
+ unsafeAccumArray f init (l,u) [(index (l,u) i, e) | (i, e) <- ies]
+
+{-# INLINE unsafeAccumArray #-}
+unsafeAccumArray :: Ix i => (e -> a -> e) -> e -> (i,i) -> [(Int, a)] -> Array i e
+unsafeAccumArray f init (l,u) ies = runST (ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newArray# n# init s1# of { (# s2#, marr# #) ->
+ foldr (adjust f marr#) (done l u marr#) ies s2# }})
+
+{-# INLINE adjust #-}
+adjust :: (e -> a -> e) -> MutableArray# s e -> (Int, a) -> STRep s b -> STRep s b
+adjust f marr# (I# i#, new) next s1# =
+ case readArray# marr# i# s1# of { (# s2#, old #) ->
+ case writeArray# marr# i# (f old new) s2# of { s3# ->
+ next s3# }}
+
+{-# INLINE (//) #-}
+(//) :: Ix i => Array i e -> [(i, e)] -> Array i e
+arr@(Array l u _) // ies =
+ unsafeReplace arr [(index (l,u) i, e) | (i, e) <- ies]
+
+{-# INLINE unsafeReplace #-}
+unsafeReplace :: Ix i => Array i e -> [(Int, e)] -> Array i e
+unsafeReplace arr@(Array l u _) ies = runST (do
+ STArray _ _ marr# <- thawSTArray arr
+ ST (foldr (fill marr#) (done l u marr#) ies))
+
+{-# INLINE accum #-}
+accum :: Ix i => (e -> a -> e) -> Array i e -> [(i, a)] -> Array i e
+accum f arr@(Array l u _) ies =
+ unsafeAccum f arr [(index (l,u) i, e) | (i, e) <- ies]
+
+{-# INLINE unsafeAccum #-}
+unsafeAccum :: Ix i => (e -> a -> e) -> Array i e -> [(Int, a)] -> Array i e
+unsafeAccum f arr@(Array l u _) ies = runST (do
+ STArray _ _ marr# <- thawSTArray arr
+ ST (foldr (adjust f marr#) (done l u marr#) ies))
+
+{-# INLINE amap #-}
+amap :: Ix i => (a -> b) -> Array i a -> Array i b
+amap f arr@(Array l u _) =
+ unsafeArray (l,u) [(i, f (unsafeAt arr i)) | i <- [0 .. rangeSize (l,u) - 1]]
+
+{-# INLINE ixmap #-}
+ixmap :: (Ix i, Ix j) => (i,i) -> (i -> j) -> Array j e -> Array i e
+ixmap (l,u) f arr =
+ unsafeArray (l,u) [(unsafeIndex (l,u) i, arr ! f i) | i <- range (l,u)]
+
+{-# INLINE eqArray #-}
+eqArray :: (Ix i, Eq e) => Array i e -> Array i e -> Bool
+eqArray arr1@(Array l1 u1 _) arr2@(Array l2 u2 _) =
+ if rangeSize (l1,u1) == 0 then rangeSize (l2,u2) == 0 else
+ l1 == l2 && u1 == u2 &&
+ and [unsafeAt arr1 i == unsafeAt arr2 i | i <- [0 .. rangeSize (l1,u1) - 1]]
+
+{-# INLINE cmpArray #-}
+cmpArray :: (Ix i, Ord e) => Array i e -> Array i e -> Ordering
+cmpArray arr1 arr2 = compare (assocs arr1) (assocs arr2)
+
+{-# INLINE cmpIntArray #-}
+cmpIntArray :: Ord e => Array Int e -> Array Int e -> Ordering
+cmpIntArray arr1@(Array l1 u1 _) arr2@(Array l2 u2 _) =
+ if rangeSize (l1,u1) == 0 then if rangeSize (l2,u2) == 0 then EQ else LT else
+ if rangeSize (l2,u2) == 0 then GT else
+ case compare l1 l2 of
+ EQ -> foldr cmp (compare u1 u2) [0 .. rangeSize (l1, min u1 u2) - 1]
+ other -> other
+ where
+ cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of
+ EQ -> rest
+ other -> other
+
+{-# RULES "cmpArray/Int" cmpArray = cmpIntArray #-}
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Array instances}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Ix i => Functor (Array i) where
+ fmap = amap
+
+instance (Ix i, Eq e) => Eq (Array i e) where
+ (==) = eqArray
+
+instance (Ix i, Ord e) => Ord (Array i e) where
+ compare = cmpArray
+
+instance (Ix a, Show a, Show b) => Show (Array a b) where
+ showsPrec p a =
+ showParen (p > 9) $
+ showString "array " .
+ shows (bounds a) .
+ showChar ' ' .
+ shows (assocs a)
+
+{-
+instance (Ix a, Read a, Read b) => Read (Array a b) where
+ readsPrec p = readParen (p > 9)
+ (\r -> [(array b as, u) | ("array",s) <- lex r,
+ (b,t) <- reads s,
+ (as,u) <- reads t ])
+-}
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Operations on mutable arrays}
+%* *
+%*********************************************************
+
+Idle ADR question: What's the tradeoff here between flattening these
+datatypes into @STArray ix ix (MutableArray# s elt)@ and using
+it as is? As I see it, the former uses slightly less heap and
+provides faster access to the individual parts of the bounds while the
+code used has the benefit of providing a ready-made @(lo, hi)@ pair as
+required by many array-related functions. Which wins? Is the
+difference significant (probably not).
+
+Idle AJG answer: When I looked at the outputted code (though it was 2
+years ago) it seems like you often needed the tuple, and we build
+it frequently. Now we've got the overloading specialiser things
+might be different, though.
+
+\begin{code}
+{-# INLINE newSTArray #-}
+newSTArray :: Ix i => (i,i) -> e -> ST s (STArray s i e)
+newSTArray (l,u) init = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newArray# n# init s1# of { (# s2#, marr# #) ->
+ (# s2#, STArray l u marr# #) }}
+
+{-# INLINE boundsSTArray #-}
+boundsSTArray :: STArray s i e -> (i,i)
+boundsSTArray (STArray l u _) = (l,u)
+
+{-# INLINE readSTArray #-}
+readSTArray :: Ix i => STArray s i e -> i -> ST s e
+readSTArray marr@(STArray l u _) i =
+ unsafeReadSTArray marr (index (l,u) i)
+
+{-# INLINE unsafeReadSTArray #-}
+unsafeReadSTArray :: Ix i => STArray s i e -> Int -> ST s e
+unsafeReadSTArray (STArray _ _ marr#) (I# i#) = ST $ \s1# ->
+ readArray# marr# i# s1#
+
+{-# INLINE writeSTArray #-}
+writeSTArray :: Ix i => STArray s i e -> i -> e -> ST s ()
+writeSTArray marr@(STArray l u _) i e =
+ unsafeWriteSTArray marr (index (l,u) i) e
+
+{-# INLINE unsafeWriteSTArray #-}
+unsafeWriteSTArray :: Ix i => STArray s i e -> Int -> e -> ST s ()
+unsafeWriteSTArray (STArray _ _ marr#) (I# i#) e = ST $ \s1# ->
+ case writeArray# marr# i# e s1# of { s2# ->
+ (# s2#, () #) }
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Moving between mutable and immutable}
+%* *
+%*********************************************************
+
+\begin{code}
+freezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)
+freezeSTArray (STArray l u marr#) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newArray# n# arrEleBottom s1# of { (# s2#, marr'# #) ->
+ let copy i# s3# | i# ==# n# = s3#
+ | otherwise =
+ case readArray# marr# i# s3# of { (# s4#, e #) ->
+ case writeArray# marr'# i# e s4# of { s5# ->
+ copy (i# +# 1#) s5# }} in
+ case copy 0# s2# of { s3# ->
+ case unsafeFreezeArray# marr'# s3# of { (# s4#, arr# #) ->
+ (# s4#, Array l u arr# #) }}}}
+
+{-# INLINE unsafeFreezeSTArray #-}
+unsafeFreezeSTArray :: Ix i => STArray s i e -> ST s (Array i e)
+unsafeFreezeSTArray (STArray l u marr#) = ST $ \s1# ->
+ case unsafeFreezeArray# marr# s1# of { (# s2#, arr# #) ->
+ (# s2#, Array l u arr# #) }
+
+thawSTArray :: Ix i => Array i e -> ST s (STArray s i e)
+thawSTArray (Array l u arr#) = ST $ \s1# ->
+ case rangeSize (l,u) of { I# n# ->
+ case newArray# n# arrEleBottom s1# of { (# s2#, marr# #) ->
+ let copy i# s3# | i# ==# n# = s3#
+ | otherwise =
+ case indexArray# arr# i# of { (# e #) ->
+ case writeArray# marr# i# e s3# of { s4# ->
+ copy (i# +# 1#) s4# }} in
+ case copy 0# s2# of { s3# ->
+ (# s3#, STArray l u marr# #) }}}
+
+{-# INLINE unsafeThawSTArray #-}
+unsafeThawSTArray :: Ix i => Array i e -> ST s (STArray s i e)
+unsafeThawSTArray (Array l u arr#) = ST $ \s1# ->
+ case unsafeThawArray# arr# s1# of { (# s2#, marr# #) ->
+ (# s2#, STArray l u marr# #) }
+\end{code}
diff --git a/libraries/base/GHC/Base.lhs b/libraries/base/GHC/Base.lhs
new file mode 100644
index 0000000000..b07bbb2c7d
--- /dev/null
+++ b/libraries/base/GHC/Base.lhs
@@ -0,0 +1,761 @@
+% -----------------------------------------------------------------------------
+% $Id: Base.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1992-2000
+%
+\section[GHC.Base]{Module @GHC.Base@}
+
+
+The overall structure of the GHC Prelude is a bit tricky.
+
+ a) We want to avoid "orphan modules", i.e. ones with instance
+ decls that don't belong either to a tycon or a class
+ defined in the same module
+
+ b) We want to avoid giant modules
+
+So the rough structure is as follows, in (linearised) dependency order
+
+
+GHC.Prim Has no implementation. It defines built-in things, and
+ by importing it you bring them into scope.
+ The source file is GHC.Prim.hi-boot, which is just
+ copied to make GHC.Prim.hi
+
+ Classes: CCallable, CReturnable
+
+GHC.Base Classes: Eq, Ord, Functor, Monad
+ Types: list, (), Int, Bool, Ordering, Char, String
+
+GHC.Tup Types: tuples, plus instances for GHC.Base classes
+
+GHC.Show Class: Show, plus instances for GHC.Base/GHC.Tup types
+
+GHC.Enum Class: Enum, plus instances for GHC.Base/GHC.Tup types
+
+GHC.Maybe Type: Maybe, plus instances for GHC.Base classes
+
+GHC.Num Class: Num, plus instances for Int
+ Type: Integer, plus instances for all classes so far (Eq, Ord, Num, Show)
+
+ Integer is needed here because it is mentioned in the signature
+ of 'fromInteger' in class Num
+
+GHC.Real Classes: Real, Integral, Fractional, RealFrac
+ plus instances for Int, Integer
+ Types: Ratio, Rational
+ plus intances for classes so far
+
+ Rational is needed here because it is mentioned in the signature
+ of 'toRational' in class Real
+
+Ix Classes: Ix, plus instances for Int, Bool, Char, Integer, Ordering, tuples
+
+GHC.Arr Types: Array, MutableArray, MutableVar
+
+ Does *not* contain any ByteArray stuff (see GHC.ByteArr)
+ Arrays are used by a function in GHC.Float
+
+GHC.Float Classes: Floating, RealFloat
+ Types: Float, Double, plus instances of all classes so far
+
+ This module contains everything to do with floating point.
+ It is a big module (900 lines)
+ With a bit of luck, many modules can be compiled without ever reading GHC.Float.hi
+
+GHC.ByteArr Types: ByteArray, MutableByteArray
+
+ We want this one to be after GHC.Float, because it defines arrays
+ of unboxed floats.
+
+
+Other Prelude modules are much easier with fewer complex dependencies.
+
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#include "MachDeps.h"
+
+module GHC.Base
+ (
+ module GHC.Base,
+ module GHC.Prim, -- Re-export GHC.Prim and GHC.Err, to avoid lots
+ module GHC.Err -- of people having to import it explicitly
+ )
+ where
+
+import GHC.Prim
+import {-# SOURCE #-} GHC.Err
+
+infixr 9 .
+infixr 5 ++, :
+infix 4 ==, /=, <, <=, >=, >
+infixr 3 &&
+infixr 2 ||
+infixl 1 >>, >>=
+infixr 0 $
+
+default () -- Double isn't available yet
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{DEBUGGING STUFF}
+%* (for use when compiling GHC.Base itself doesn't work)
+%* *
+%*********************************************************
+
+\begin{code}
+{-
+data Bool = False | True
+data Ordering = LT | EQ | GT
+data Char = C# Char#
+type String = [Char]
+data Int = I# Int#
+data () = ()
+data [] a = MkNil
+
+not True = False
+(&&) True True = True
+otherwise = True
+
+build = error "urk"
+foldr = error "urk"
+
+unpackCString# :: Addr# -> [Char]
+unpackFoldrCString# :: Addr# -> (Char -> a -> a) -> a -> a
+unpackAppendCString# :: Addr# -> [Char] -> [Char]
+unpackCStringUtf8# :: Addr# -> [Char]
+unpackCString# a = error "urk"
+unpackFoldrCString# a = error "urk"
+unpackAppendCString# a = error "urk"
+unpackCStringUtf8# a = error "urk"
+-}
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Standard classes @Eq@, @Ord@}
+%* *
+%*********************************************************
+
+\begin{code}
+class Eq a where
+ (==), (/=) :: a -> a -> Bool
+
+ x /= y = not (x == y)
+ x == y = not (x /= y)
+
+class (Eq a) => Ord a where
+ compare :: a -> a -> Ordering
+ (<), (<=), (>), (>=) :: a -> a -> Bool
+ max, min :: a -> a -> a
+
+ -- An instance of Ord should define either 'compare' or '<='.
+ -- Using 'compare' can be more efficient for complex types.
+
+ compare x y
+ | x == y = EQ
+ | x <= y = LT -- NB: must be '<=' not '<' to validate the
+ -- above claim about the minimal things that
+ -- can be defined for an instance of Ord
+ | otherwise = GT
+
+ x < y = case compare x y of { LT -> True; _other -> False }
+ x <= y = case compare x y of { GT -> False; _other -> True }
+ x > y = case compare x y of { GT -> True; _other -> False }
+ x >= y = case compare x y of { LT -> False; _other -> True }
+
+ -- These two default methods use '<=' rather than 'compare'
+ -- because the latter is often more expensive
+ max x y = if x <= y then y else x
+ min x y = if x <= y then x else y
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Monadic classes @Functor@, @Monad@ }
+%* *
+%*********************************************************
+
+\begin{code}
+class Functor f where
+ fmap :: (a -> b) -> f a -> f b
+
+class Monad m where
+ (>>=) :: m a -> (a -> m b) -> m b
+ (>>) :: m a -> m b -> m b
+ return :: a -> m a
+ fail :: String -> m a
+
+ m >> k = m >>= \_ -> k
+ fail s = error s
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The list type}
+%* *
+%*********************************************************
+
+\begin{code}
+data [] a = [] | a : [a] -- do explicitly: deriving (Eq, Ord)
+ -- to avoid weird names like con2tag_[]#
+
+
+instance (Eq a) => Eq [a] where
+ {-# SPECIALISE instance Eq [Char] #-}
+ [] == [] = True
+ (x:xs) == (y:ys) = x == y && xs == ys
+ _xs == _ys = False
+
+instance (Ord a) => Ord [a] where
+ {-# SPECIALISE instance Ord [Char] #-}
+ compare [] [] = EQ
+ compare [] (_:_) = LT
+ compare (_:_) [] = GT
+ compare (x:xs) (y:ys) = case compare x y of
+ EQ -> compare xs ys
+ other -> other
+
+instance Functor [] where
+ fmap = map
+
+instance Monad [] where
+ m >>= k = foldr ((++) . k) [] m
+ m >> k = foldr ((++) . (\ _ -> k)) [] m
+ return x = [x]
+ fail _ = []
+\end{code}
+
+A few list functions that appear here because they are used here.
+The rest of the prelude list functions are in GHC.List.
+
+----------------------------------------------
+-- foldr/build/augment
+----------------------------------------------
+
+\begin{code}
+foldr :: (a -> b -> b) -> b -> [a] -> b
+-- foldr _ z [] = z
+-- foldr f z (x:xs) = f x (foldr f z xs)
+{-# INLINE foldr #-}
+foldr k z xs = go xs
+ where
+ go [] = z
+ go (y:ys) = y `k` go ys
+
+build :: forall a. (forall b. (a -> b -> b) -> b -> b) -> [a]
+{-# INLINE 2 build #-}
+ -- The INLINE is important, even though build is tiny,
+ -- because it prevents [] getting inlined in the version that
+ -- appears in the interface file. If [] *is* inlined, it
+ -- won't match with [] appearing in rules in an importing module.
+ --
+ -- The "2" says to inline in phase 2
+
+build g = g (:) []
+
+augment :: forall a. (forall b. (a->b->b) -> b -> b) -> [a] -> [a]
+{-# INLINE 2 augment #-}
+augment g xs = g (:) xs
+
+{-# RULES
+"fold/build" forall k z (g::forall b. (a->b->b) -> b -> b) .
+ foldr k z (build g) = g k z
+
+"foldr/augment" forall k z xs (g::forall b. (a->b->b) -> b -> b) .
+ foldr k z (augment g xs) = g k (foldr k z xs)
+
+"foldr/id" foldr (:) [] = \x->x
+"foldr/app" forall xs ys. foldr (:) ys xs = append xs ys
+
+"foldr/cons" forall k z x xs. foldr k z (x:xs) = k x (foldr k z xs)
+"foldr/nil" forall k z. foldr k z [] = z
+
+"augment/build" forall (g::forall b. (a->b->b) -> b -> b)
+ (h::forall b. (a->b->b) -> b -> b) .
+ augment g (build h) = build (\c n -> g c (h c n))
+"augment/nil" forall (g::forall b. (a->b->b) -> b -> b) .
+ augment g [] = build g
+ #-}
+
+-- This rule is true, but not (I think) useful:
+-- augment g (augment h t) = augment (\cn -> g c (h c n)) t
+\end{code}
+
+
+----------------------------------------------
+-- map
+----------------------------------------------
+
+\begin{code}
+map :: (a -> b) -> [a] -> [b]
+map = mapList
+
+-- Note eta expanded
+mapFB :: (elt -> lst -> lst) -> (a -> elt) -> a -> lst -> lst
+mapFB c f x ys = c (f x) ys
+
+mapList :: (a -> b) -> [a] -> [b]
+mapList _ [] = []
+mapList f (x:xs) = f x : mapList f xs
+
+{-# RULES
+"map" forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)
+"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f.g)
+"mapList" forall f. foldr (mapFB (:) f) [] = mapList f
+ #-}
+\end{code}
+
+
+----------------------------------------------
+-- append
+----------------------------------------------
+\begin{code}
+(++) :: [a] -> [a] -> [a]
+(++) = append
+
+{-# RULES
+"++" forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
+ #-}
+
+append :: [a] -> [a] -> [a]
+append [] ys = ys
+append (x:xs) ys = x : append xs ys
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Type @Bool@}
+%* *
+%*********************************************************
+
+\begin{code}
+data Bool = False | True deriving (Eq, Ord)
+ -- Read in GHC.Read, Show in GHC.Show
+
+-- Boolean functions
+
+(&&), (||) :: Bool -> Bool -> Bool
+True && x = x
+False && _ = False
+True || _ = True
+False || x = x
+
+not :: Bool -> Bool
+not True = False
+not False = True
+
+otherwise :: Bool
+otherwise = True
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @()@ type}
+%* *
+%*********************************************************
+
+The Unit type is here because virtually any program needs it (whereas
+some programs may get away without consulting GHC.Tup). Furthermore,
+the renamer currently *always* asks for () to be in scope, so that
+ccalls can use () as their default type; so when compiling GHC.Base we
+need (). (We could arrange suck in () only if -fglasgow-exts, but putting
+it here seems more direct.)
+
+\begin{code}
+data () = ()
+
+instance Eq () where
+ () == () = True
+ () /= () = False
+
+instance Ord () where
+ () <= () = True
+ () < () = False
+ () >= () = True
+ () > () = False
+ max () () = ()
+ min () () = ()
+ compare () () = EQ
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Type @Ordering@}
+%* *
+%*********************************************************
+
+\begin{code}
+data Ordering = LT | EQ | GT deriving (Eq, Ord)
+ -- Read in GHC.Read, Show in GHC.Show
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Type @Char@ and @String@}
+%* *
+%*********************************************************
+
+\begin{code}
+type String = [Char]
+
+data Char = C# Char#
+
+-- We don't use deriving for Eq and Ord, because for Ord the derived
+-- instance defines only compare, which takes two primops. Then
+-- '>' uses compare, and therefore takes two primops instead of one.
+
+instance Eq Char where
+ (C# c1) == (C# c2) = c1 `eqChar#` c2
+ (C# c1) /= (C# c2) = c1 `neChar#` c2
+
+instance Ord Char where
+ (C# c1) > (C# c2) = c1 `gtChar#` c2
+ (C# c1) >= (C# c2) = c1 `geChar#` c2
+ (C# c1) <= (C# c2) = c1 `leChar#` c2
+ (C# c1) < (C# c2) = c1 `ltChar#` c2
+
+{-# RULES
+"x# `eqChar#` x#" forall x#. x# `eqChar#` x# = True
+"x# `neChar#` x#" forall x#. x# `neChar#` x# = False
+"x# `gtChar#` x#" forall x#. x# `gtChar#` x# = False
+"x# `geChar#` x#" forall x#. x# `geChar#` x# = True
+"x# `leChar#` x#" forall x#. x# `leChar#` x# = True
+"x# `ltChar#` x#" forall x#. x# `ltChar#` x# = False
+ #-}
+
+chr :: Int -> Char
+chr (I# i#) | int2Word# i# `leWord#` int2Word# 0x10FFFF# = C# (chr# i#)
+ | otherwise = error "Prelude.chr: bad argument"
+
+unsafeChr :: Int -> Char
+unsafeChr (I# i#) = C# (chr# i#)
+
+ord :: Char -> Int
+ord (C# c#) = I# (ord# c#)
+\end{code}
+
+String equality is used when desugaring pattern-matches against strings.
+
+\begin{code}
+eqString :: String -> String -> Bool
+eqString = (==)
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Type @Int@}
+%* *
+%*********************************************************
+
+\begin{code}
+data Int = I# Int#
+
+zeroInt, oneInt, twoInt, maxInt, minInt :: Int
+zeroInt = I# 0#
+oneInt = I# 1#
+twoInt = I# 2#
+#if WORD_SIZE_IN_BYTES == 4
+minInt = I# (-0x80000000#)
+maxInt = I# 0x7FFFFFFF#
+#else
+minInt = I# (-0x8000000000000000#)
+maxInt = I# 0x7FFFFFFFFFFFFFFF#
+#endif
+
+instance Eq Int where
+ (==) = eqInt
+ (/=) = neInt
+
+instance Ord Int where
+ compare = compareInt
+ (<) = ltInt
+ (<=) = leInt
+ (>=) = geInt
+ (>) = gtInt
+
+compareInt :: Int -> Int -> Ordering
+(I# x#) `compareInt` (I# y#) = compareInt# x# y#
+
+compareInt# :: Int# -> Int# -> Ordering
+compareInt# x# y#
+ | x# <# y# = LT
+ | x# ==# y# = EQ
+ | otherwise = GT
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The function type}
+%* *
+%*********************************************************
+
+\begin{code}
+-- identity function
+id :: a -> a
+id x = x
+
+-- constant function
+const :: a -> b -> a
+const x _ = x
+
+-- function composition
+{-# INLINE (.) #-}
+(.) :: (b -> c) -> (a -> b) -> a -> c
+(.) f g x = f (g x)
+
+-- flip f takes its (first) two arguments in the reverse order of f.
+flip :: (a -> b -> c) -> b -> a -> c
+flip f x y = f y x
+
+-- right-associating infix application operator (useful in continuation-
+-- passing style)
+{-# INLINE ($) #-}
+($) :: (a -> b) -> a -> b
+f $ x = f x
+
+-- until p f yields the result of applying f until p holds.
+until :: (a -> Bool) -> (a -> a) -> a -> a
+until p f x | p x = x
+ | otherwise = until p f (f x)
+
+-- asTypeOf is a type-restricted version of const. It is usually used
+-- as an infix operator, and its typing forces its first argument
+-- (which is usually overloaded) to have the same type as the second.
+asTypeOf :: a -> a -> a
+asTypeOf = const
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{CCallable instances}
+%* *
+%*********************************************************
+
+Defined here to avoid orphans
+
+\begin{code}
+instance CCallable Char
+instance CReturnable Char
+
+instance CCallable Int
+instance CReturnable Int
+
+instance CReturnable () -- Why, exactly?
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Generics}
+%* *
+%*********************************************************
+
+\begin{code}
+data Unit = Unit
+data a :+: b = Inl a | Inr b
+data a :*: b = a :*: b
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Numeric primops}
+%* *
+%*********************************************************
+
+\begin{code}
+divInt#, modInt# :: Int# -> Int# -> Int#
+x# `divInt#` y#
+ | (x# ># 0#) && (y# <# 0#) = ((x# -# y#) -# 1#) `quotInt#` y#
+ | (x# <# 0#) && (y# ># 0#) = ((x# -# y#) +# 1#) `quotInt#` y#
+ | otherwise = x# `quotInt#` y#
+x# `modInt#` y#
+ | (x# ># 0#) && (y# <# 0#) ||
+ (x# <# 0#) && (y# ># 0#) = if r# /=# 0# then r# +# y# else 0#
+ | otherwise = r#
+ where
+ r# = x# `remInt#` y#
+\end{code}
+
+Definitions of the boxed PrimOps; these will be
+used in the case of partial applications, etc.
+
+\begin{code}
+{-# INLINE eqInt #-}
+{-# INLINE neInt #-}
+{-# INLINE gtInt #-}
+{-# INLINE geInt #-}
+{-# INLINE ltInt #-}
+{-# INLINE leInt #-}
+{-# INLINE plusInt #-}
+{-# INLINE minusInt #-}
+{-# INLINE timesInt #-}
+{-# INLINE quotInt #-}
+{-# INLINE remInt #-}
+{-# INLINE negateInt #-}
+
+plusInt, minusInt, timesInt, quotInt, remInt, divInt, modInt, gcdInt :: Int -> Int -> Int
+(I# x) `plusInt` (I# y) = I# (x +# y)
+(I# x) `minusInt` (I# y) = I# (x -# y)
+(I# x) `timesInt` (I# y) = I# (x *# y)
+(I# x) `quotInt` (I# y) = I# (x `quotInt#` y)
+(I# x) `remInt` (I# y) = I# (x `remInt#` y)
+(I# x) `divInt` (I# y) = I# (x `divInt#` y)
+(I# x) `modInt` (I# y) = I# (x `modInt#` y)
+
+{-# RULES
+"x# +# 0#" forall x#. x# +# 0# = x#
+"0# +# x#" forall x#. 0# +# x# = x#
+"x# -# 0#" forall x#. x# -# 0# = x#
+"x# -# x#" forall x#. x# -# x# = 0#
+"x# *# 0#" forall x#. x# *# 0# = 0#
+"0# *# x#" forall x#. 0# *# x# = 0#
+"x# *# 1#" forall x#. x# *# 1# = x#
+"1# *# x#" forall x#. 1# *# x# = x#
+ #-}
+
+gcdInt (I# a) (I# b) = g a b
+ where g 0# 0# = error "GHC.Base.gcdInt: gcd 0 0 is undefined"
+ g 0# _ = I# absB
+ g _ 0# = I# absA
+ g _ _ = I# (gcdInt# absA absB)
+
+ absInt x = if x <# 0# then negateInt# x else x
+
+ absA = absInt a
+ absB = absInt b
+
+negateInt :: Int -> Int
+negateInt (I# x) = I# (negateInt# x)
+
+gtInt, geInt, eqInt, neInt, ltInt, leInt :: Int -> Int -> Bool
+(I# x) `gtInt` (I# y) = x ># y
+(I# x) `geInt` (I# y) = x >=# y
+(I# x) `eqInt` (I# y) = x ==# y
+(I# x) `neInt` (I# y) = x /=# y
+(I# x) `ltInt` (I# y) = x <# y
+(I# x) `leInt` (I# y) = x <=# y
+
+{-# RULES
+"x# ># x#" forall x#. x# ># x# = False
+"x# >=# x#" forall x#. x# >=# x# = True
+"x# ==# x#" forall x#. x# ==# x# = True
+"x# /=# x#" forall x#. x# /=# x# = False
+"x# <# x#" forall x#. x# <# x# = False
+"x# <=# x#" forall x#. x# <=# x# = True
+ #-}
+
+#if WORD_SIZE_IN_BYTES == 4
+{-# RULES
+"intToInt32#" forall x#. intToInt32# x# = x#
+"wordToWord32#" forall x#. wordToWord32# x# = x#
+ #-}
+#endif
+
+{-# RULES
+"int2Word2Int" forall x#. int2Word# (word2Int# x#) = x#
+"word2Int2Word" forall x#. word2Int# (int2Word# x#) = x#
+ #-}
+\end{code}
+
+
+%********************************************************
+%* *
+\subsection{Unpacking C strings}
+%* *
+%********************************************************
+
+This code is needed for virtually all programs, since it's used for
+unpacking the strings of error messages.
+
+\begin{code}
+unpackCString# :: Addr# -> [Char]
+unpackCString# a = unpackCStringList# a
+
+unpackCStringList# :: Addr# -> [Char]
+unpackCStringList# addr
+ = unpack 0#
+ where
+ unpack nh
+ | ch `eqChar#` '\0'# = []
+ | otherwise = C# ch : unpack (nh +# 1#)
+ where
+ ch = indexCharOffAddr# addr nh
+
+unpackAppendCString# :: Addr# -> [Char] -> [Char]
+unpackAppendCString# addr rest
+ = unpack 0#
+ where
+ unpack nh
+ | ch `eqChar#` '\0'# = rest
+ | otherwise = C# ch : unpack (nh +# 1#)
+ where
+ ch = indexCharOffAddr# addr nh
+
+unpackFoldrCString# :: Addr# -> (Char -> a -> a) -> a -> a
+unpackFoldrCString# addr f z
+ = unpack 0#
+ where
+ unpack nh
+ | ch `eqChar#` '\0'# = z
+ | otherwise = C# ch `f` unpack (nh +# 1#)
+ where
+ ch = indexCharOffAddr# addr nh
+
+unpackCStringUtf8# :: Addr# -> [Char]
+unpackCStringUtf8# addr
+ = unpack 0#
+ where
+ unpack nh
+ | ch `eqChar#` '\0'# = []
+ | ch `leChar#` '\x7F'# = C# ch : unpack (nh +# 1#)
+ | ch `leChar#` '\xDF'# =
+ C# (chr# ((ord# ch -# 0xC0#) `iShiftL#` 6# +#
+ (ord# (indexCharOffAddr# addr (nh +# 1#)) -# 0x80#))) :
+ unpack (nh +# 2#)
+ | ch `leChar#` '\xEF'# =
+ C# (chr# ((ord# ch -# 0xE0#) `iShiftL#` 12# +#
+ (ord# (indexCharOffAddr# addr (nh +# 1#)) -# 0x80#) `iShiftL#` 6# +#
+ (ord# (indexCharOffAddr# addr (nh +# 2#)) -# 0x80#))) :
+ unpack (nh +# 3#)
+ | otherwise =
+ C# (chr# ((ord# ch -# 0xF0#) `iShiftL#` 18# +#
+ (ord# (indexCharOffAddr# addr (nh +# 1#)) -# 0x80#) `iShiftL#` 12# +#
+ (ord# (indexCharOffAddr# addr (nh +# 2#)) -# 0x80#) `iShiftL#` 6# +#
+ (ord# (indexCharOffAddr# addr (nh +# 3#)) -# 0x80#))) :
+ unpack (nh +# 4#)
+ where
+ ch = indexCharOffAddr# addr nh
+
+unpackNBytes# :: Addr# -> Int# -> [Char]
+unpackNBytes# _addr 0# = []
+unpackNBytes# addr len# = unpack [] (len# -# 1#)
+ where
+ unpack acc i#
+ | i# <# 0# = acc
+ | otherwise =
+ case indexCharOffAddr# addr i# of
+ ch -> unpack (C# ch : acc) (i# -# 1#)
+
+{-# RULES
+"unpack" forall a . unpackCString# a = build (unpackFoldrCString# a)
+"unpack-list" forall a . unpackFoldrCString# a (:) [] = unpackCStringList# a
+"unpack-append" forall a n . unpackFoldrCString# a (:) n = unpackAppendCString# a n
+
+-- There's a built-in rule (in GHC.Rules.lhs) for
+-- unpackFoldr "foo" c (unpackFoldr "baz" c n) = unpackFoldr "foobaz" c n
+
+ #-}
+\end{code}
diff --git a/libraries/base/GHC/ByteArr.lhs b/libraries/base/GHC/ByteArr.lhs
new file mode 100644
index 0000000000..49756fa761
--- /dev/null
+++ b/libraries/base/GHC/ByteArr.lhs
@@ -0,0 +1,184 @@
+% -----------------------------------------------------------------------------
+% $Id: ByteArr.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.ByteArr]{Module @GHC.ByteArr@}
+
+Byte-arrays are flat arrays of non-pointers only.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.ByteArr where
+
+import {-# SOURCE #-} GHC.Err ( error )
+import GHC.Num
+import GHC.Arr
+import GHC.Float
+import GHC.ST
+import GHC.Base
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{The @Array@ types}
+%* *
+%*********************************************************
+
+\begin{code}
+data Ix ix => ByteArray ix = ByteArray ix ix ByteArray#
+data Ix ix => MutableByteArray s ix = MutableByteArray ix ix (MutableByteArray# s)
+
+instance CCallable (ByteArray ix)
+instance CCallable (MutableByteArray RealWorld ix)
+ -- Note the RealWorld! You can only ccall with MutableByteArray args
+ -- which are in the real world. When this was missed out, the result
+ -- was that a CCallOpId had a free tyvar, and since the compiler doesn't
+ -- expect that it didn't get zonked or substituted. Bad news.
+
+instance Eq (MutableByteArray s ix) where
+ MutableByteArray _ _ arr1# == MutableByteArray _ _ arr2#
+ = sameMutableByteArray# arr1# arr2#
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Operations on mutable arrays}
+%* *
+%*********************************************************
+
+\begin{code}
+newCharArray, newIntArray, newFloatArray, newDoubleArray
+ :: Ix ix => (ix,ix) -> ST s (MutableByteArray s ix)
+
+{-# SPECIALIZE newCharArray :: IPr -> ST s (MutableByteArray s Int) #-}
+{-# SPECIALIZE newIntArray :: IPr -> ST s (MutableByteArray s Int) #-}
+{-# SPECIALIZE newFloatArray :: IPr -> ST s (MutableByteArray s Int) #-}
+{-# SPECIALIZE newDoubleArray :: IPr -> ST s (MutableByteArray s Int) #-}
+
+newCharArray (l,u) = ST $ \ s# ->
+ case rangeSize (l,u) of { I# n# ->
+ case (newByteArray# (cHAR_SCALE n#) s#) of { (# s2#, barr# #) ->
+ (# s2#, MutableByteArray l u barr# #) }}
+
+newIntArray (l,u) = ST $ \ s# ->
+ case rangeSize (l,u) of { I# n# ->
+ case (newByteArray# (wORD_SCALE n#) s#) of { (# s2#, barr# #) ->
+ (# s2#, MutableByteArray l u barr# #) }}
+
+newWordArray (l,u) = ST $ \ s# ->
+ case rangeSize (l,u) of { I# n# ->
+ case (newByteArray# (wORD_SCALE n#) s#) of { (# s2#, barr# #) ->
+ (# s2#, MutableByteArray l u barr# #) }}
+
+newFloatArray (l,u) = ST $ \ s# ->
+ case rangeSize (l,u) of { I# n# ->
+ case (newByteArray# (fLOAT_SCALE n#) s#) of { (# s2#, barr# #) ->
+ (# s2#, MutableByteArray l u barr# #) }}
+
+newDoubleArray (l,u) = ST $ \ s# ->
+ case rangeSize (l,u) of { I# n# ->
+ case (newByteArray# (dOUBLE_SCALE n#) s#) of { (# s2#, barr# #) ->
+ (# s2#, MutableByteArray l u barr# #) }}
+
+#include "config.h"
+
+ -- Char arrays really contain only 8-bit bytes for compatibility.
+cHAR_SCALE n = 1# *# n
+wORD_SCALE n = (case SIZEOF_VOID_P :: Int of I# x -> x *# n)
+dOUBLE_SCALE n = (case SIZEOF_DOUBLE :: Int of I# x -> x *# n)
+fLOAT_SCALE n = (case SIZEOF_FLOAT :: Int of I# x -> x *# n)
+
+readCharArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Char
+readIntArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Int
+readFloatArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Float
+readDoubleArray :: Ix ix => MutableByteArray s ix -> ix -> ST s Double
+
+{-# SPECIALIZE readCharArray :: MutableByteArray s Int -> Int -> ST s Char #-}
+{-# SPECIALIZE readIntArray :: MutableByteArray s Int -> Int -> ST s Int #-}
+--NO:{-# SPECIALIZE readFloatArray :: MutableByteArray s Int -> Int -> ST s Float #-}
+{-# SPECIALIZE readDoubleArray :: MutableByteArray s Int -> Int -> ST s Double #-}
+
+readCharArray (MutableByteArray l u barr#) n = ST $ \ s# ->
+ case (index (l,u) n) of { I# n# ->
+ case readCharArray# barr# n# s# of { (# s2#, r# #) ->
+ (# s2#, C# r# #) }}
+
+readIntArray (MutableByteArray l u barr#) n = ST $ \ s# ->
+ case (index (l,u) n) of { I# n# ->
+ case readIntArray# barr# n# s# of { (# s2#, r# #) ->
+ (# s2#, I# r# #) }}
+
+readFloatArray (MutableByteArray l u barr#) n = ST $ \ s# ->
+ case (index (l,u) n) of { I# n# ->
+ case readFloatArray# barr# n# s# of { (# s2#, r# #) ->
+ (# s2#, F# r# #) }}
+
+readDoubleArray (MutableByteArray l u barr#) n = ST $ \ s# ->
+ case (index (l,u) n) of { I# n# ->
+ case readDoubleArray# barr# n# s# of { (# s2#, r# #) ->
+ (# s2#, D# r# #) }}
+
+--Indexing of ordinary @Arrays@ is standard Haskell and isn't defined here.
+indexCharArray :: Ix ix => ByteArray ix -> ix -> Char
+indexIntArray :: Ix ix => ByteArray ix -> ix -> Int
+indexFloatArray :: Ix ix => ByteArray ix -> ix -> Float
+indexDoubleArray :: Ix ix => ByteArray ix -> ix -> Double
+
+{-# SPECIALIZE indexCharArray :: ByteArray Int -> Int -> Char #-}
+{-# SPECIALIZE indexIntArray :: ByteArray Int -> Int -> Int #-}
+--NO:{-# SPECIALIZE indexFloatArray :: ByteArray Int -> Int -> Float #-}
+{-# SPECIALIZE indexDoubleArray :: ByteArray Int -> Int -> Double #-}
+
+indexCharArray (ByteArray l u barr#) n
+ = case (index (l,u) n) of { I# n# ->
+ case indexCharArray# barr# n# of { r# ->
+ (C# r#)}}
+
+indexIntArray (ByteArray l u barr#) n
+ = case (index (l,u) n) of { I# n# ->
+ case indexIntArray# barr# n# of { r# ->
+ (I# r#)}}
+
+indexFloatArray (ByteArray l u barr#) n
+ = case (index (l,u) n) of { I# n# ->
+ case indexFloatArray# barr# n# of { r# ->
+ (F# r#)}}
+
+indexDoubleArray (ByteArray l u barr#) n
+ = case (index (l,u) n) of { I# n# ->
+ case indexDoubleArray# barr# n# of { r# ->
+ (D# r#)}}
+
+writeCharArray :: Ix ix => MutableByteArray s ix -> ix -> Char -> ST s ()
+writeIntArray :: Ix ix => MutableByteArray s ix -> ix -> Int -> ST s ()
+writeFloatArray :: Ix ix => MutableByteArray s ix -> ix -> Float -> ST s ()
+writeDoubleArray :: Ix ix => MutableByteArray s ix -> ix -> Double -> ST s ()
+
+{-# SPECIALIZE writeCharArray :: MutableByteArray s Int -> Int -> Char -> ST s () #-}
+{-# SPECIALIZE writeIntArray :: MutableByteArray s Int -> Int -> Int -> ST s () #-}
+--NO:{-# SPECIALIZE writeFloatArray :: MutableByteArray s Int -> Int -> Float -> ST s () #-}
+{-# SPECIALIZE writeDoubleArray :: MutableByteArray s Int -> Int -> Double -> ST s () #-}
+
+writeCharArray (MutableByteArray l u barr#) n (C# ele) = ST $ \ s# ->
+ case index (l,u) n of { I# n# ->
+ case writeCharArray# barr# n# ele s# of { s2# ->
+ (# s2#, () #) }}
+
+writeIntArray (MutableByteArray l u barr#) n (I# ele) = ST $ \ s# ->
+ case index (l,u) n of { I# n# ->
+ case writeIntArray# barr# n# ele s# of { s2# ->
+ (# s2#, () #) }}
+
+writeFloatArray (MutableByteArray l u barr#) n (F# ele) = ST $ \ s# ->
+ case index (l,u) n of { I# n# ->
+ case writeFloatArray# barr# n# ele s# of { s2# ->
+ (# s2#, () #) }}
+
+writeDoubleArray (MutableByteArray l u barr#) n (D# ele) = ST $ \ s# ->
+ case index (l,u) n of { I# n# ->
+ case writeDoubleArray# barr# n# ele s# of { s2# ->
+ (# s2#, () #) }}
+\end{code}
diff --git a/libraries/base/GHC/Conc.lhs b/libraries/base/GHC/Conc.lhs
new file mode 100644
index 0000000000..57daaf8cfa
--- /dev/null
+++ b/libraries/base/GHC/Conc.lhs
@@ -0,0 +1,202 @@
+% -----------------------------------------------------------------------------
+% $Id: Conc.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Conc]{Module @GHC.Conc@}
+
+Basic concurrency stuff
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Conc
+ ( ThreadId(..)
+
+ -- Forking and suchlike
+ , myThreadId -- :: IO ThreadId
+ , killThread -- :: ThreadId -> IO ()
+ , throwTo -- :: ThreadId -> Exception -> IO ()
+ , par -- :: a -> b -> b
+ , seq -- :: a -> b -> b
+ , yield -- :: IO ()
+
+ -- Waiting
+ , threadDelay -- :: Int -> IO ()
+ , threadWaitRead -- :: Int -> IO ()
+ , threadWaitWrite -- :: Int -> IO ()
+
+ -- MVars
+ , MVar -- abstract
+ , newMVar -- :: a -> IO (MVar a)
+ , newEmptyMVar -- :: IO (MVar a)
+ , takeMVar -- :: MVar a -> IO a
+ , putMVar -- :: MVar a -> a -> IO ()
+ , tryTakeMVar -- :: MVar a -> IO (Maybe a)
+ , tryPutMVar -- :: MVar a -> a -> IO Bool
+ , isEmptyMVar -- :: MVar a -> IO Bool
+ , addMVarFinalizer -- :: MVar a -> IO () -> IO ()
+
+ ) where
+
+import GHC.Base
+import GHC.Maybe
+import GHC.Err ( parError, seqError )
+import GHC.IOBase ( IO(..), MVar(..) )
+import GHC.Base ( Int(..) )
+import GHC.Exception ( Exception(..), AsyncException(..) )
+
+infixr 0 `par`, `seq`
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{@ThreadId@, @par@, and @fork@}
+%* *
+%************************************************************************
+
+\begin{code}
+data ThreadId = ThreadId ThreadId#
+-- ToDo: data ThreadId = ThreadId (Weak ThreadId#)
+-- But since ThreadId# is unlifted, the Weak type must use open
+-- type variables.
+
+--forkIO has now been hoisted out into the Concurrent library.
+
+killThread :: ThreadId -> IO ()
+killThread (ThreadId id) = IO $ \ s ->
+ case (killThread# id (AsyncException ThreadKilled) s) of s1 -> (# s1, () #)
+
+throwTo :: ThreadId -> Exception -> IO ()
+throwTo (ThreadId id) ex = IO $ \ s ->
+ case (killThread# id ex s) of s1 -> (# s1, () #)
+
+myThreadId :: IO ThreadId
+myThreadId = IO $ \s ->
+ case (myThreadId# s) of (# s1, id #) -> (# s1, ThreadId id #)
+
+yield :: IO ()
+yield = IO $ \s ->
+ case (yield# s) of s1 -> (# s1, () #)
+
+-- "seq" is defined a bit weirdly (see below)
+--
+-- The reason for the strange "0# -> parError" case is that
+-- it fools the compiler into thinking that seq is non-strict in
+-- its second argument (even if it inlines seq at the call site).
+-- If it thinks seq is strict in "y", then it often evaluates
+-- "y" before "x", which is totally wrong.
+--
+-- Just before converting from Core to STG there's a bit of magic
+-- that recognises the seq# and eliminates the duff case.
+
+{-# INLINE seq #-}
+seq :: a -> b -> b
+seq x y = case (seq# x) of { 0# -> seqError; _ -> y }
+
+{-# INLINE par #-}
+par :: a -> b -> b
+par x y = case (par# x) of { 0# -> parError; _ -> y }
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[mvars]{M-Structures}
+%* *
+%************************************************************************
+
+M-Vars are rendezvous points for concurrent threads. They begin
+empty, and any attempt to read an empty M-Var blocks. When an M-Var
+is written, a single blocked thread may be freed. Reading an M-Var
+toggles its state from full back to empty. Therefore, any value
+written to an M-Var may only be read once. Multiple reads and writes
+are allowed, but there must be at least one read between any two
+writes.
+
+\begin{code}
+--Defined in IOBase to avoid cycle: data MVar a = MVar (SynchVar# RealWorld a)
+
+newEmptyMVar :: IO (MVar a)
+newEmptyMVar = IO $ \ s# ->
+ case newMVar# s# of
+ (# s2#, svar# #) -> (# s2#, MVar svar# #)
+
+takeMVar :: MVar a -> IO a
+takeMVar (MVar mvar#) = IO $ \ s# -> takeMVar# mvar# s#
+
+putMVar :: MVar a -> a -> IO ()
+putMVar (MVar mvar#) x = IO $ \ s# ->
+ case putMVar# mvar# x s# of
+ s2# -> (# s2#, () #)
+
+tryPutMVar :: MVar a -> a -> IO Bool
+tryPutMVar (MVar mvar#) x = IO $ \ s# ->
+ case tryPutMVar# mvar# x s# of
+ (# s, 0# #) -> (# s, False #)
+ (# s, _ #) -> (# s, True #)
+
+newMVar :: a -> IO (MVar a)
+newMVar value =
+ newEmptyMVar >>= \ mvar ->
+ putMVar mvar value >>
+ return mvar
+
+-- tryTakeMVar is a non-blocking takeMVar
+tryTakeMVar :: MVar a -> IO (Maybe a)
+tryTakeMVar (MVar m) = IO $ \ s ->
+ case tryTakeMVar# m s of
+ (# s, 0#, _ #) -> (# s, Nothing #) -- MVar is empty
+ (# s, _, a #) -> (# s, Just a #) -- MVar is full
+
+{-
+ Low-level op. for checking whether an MVar is filled-in or not.
+ Notice that the boolean value returned is just a snapshot of
+ the state of the MVar. By the time you get to react on its result,
+ the MVar may have been filled (or emptied) - so be extremely
+ careful when using this operation.
+
+ Use tryTakeMVar instead if possible.
+
+ If you can re-work your abstractions to avoid having to
+ depend on isEmptyMVar, then you're encouraged to do so,
+ i.e., consider yourself warned about the imprecision in
+ general of isEmptyMVar :-)
+-}
+isEmptyMVar :: MVar a -> IO Bool
+isEmptyMVar (MVar mv#) = IO $ \ s# ->
+ case isEmptyMVar# mv# s# of
+ (# s2#, flg #) -> (# s2#, not (flg ==# 0#) #)
+
+-- Like addForeignPtrFinalizer, but for MVars
+addMVarFinalizer :: MVar a -> IO () -> IO ()
+addMVarFinalizer (MVar m) finalizer =
+ IO $ \s -> case mkWeak# m () finalizer s of { (# s1, w #) -> (# s1, () #) }
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Thread waiting}
+%* *
+%************************************************************************
+
+@threadDelay@ delays rescheduling of a thread until the indicated
+number of microseconds have elapsed. Generally, the microseconds are
+counted by the context switch timer, which ticks in virtual time;
+however, when there are no runnable threads, we don't accumulate any
+virtual time, so we start ticking in real time. (The granularity is
+the effective resolution of the context switch timer, so it is
+affected by the RTS -C option.)
+
+@threadWaitRead@ delays rescheduling of a thread until input on the
+specified file descriptor is available for reading (just like select).
+@threadWaitWrite@ is similar, but for writing on a file descriptor.
+
+\begin{code}
+threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
+
+threadDelay (I# ms) = IO $ \s -> case delay# ms s of s -> (# s, () #)
+threadWaitRead (I# fd) = IO $ \s -> case waitRead# fd s of s -> (# s, () #)
+threadWaitWrite (I# fd) = IO $ \s -> case waitWrite# fd s of s -> (# s, () #)
+\end{code}
diff --git a/libraries/base/GHC/Dynamic.lhs b/libraries/base/GHC/Dynamic.lhs
new file mode 100644
index 0000000000..1cd8675dd3
--- /dev/null
+++ b/libraries/base/GHC/Dynamic.lhs
@@ -0,0 +1,35 @@
+% -----------------------------------------------------------------------------
+% $Id: Dynamic.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1998-2000
+%
+
+The Dynamic type is used in the Exception type, so we have to have
+Dynamic visible here. The rest of the operations on Dynamics are
+available in lang/Dynamic.lhs.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#ifndef __HUGS__
+module GHC.Dynamic where
+
+import GHC.Base
+#endif
+
+data Dynamic = Dynamic TypeRep Obj
+
+data Obj = Obj
+ -- dummy type to hold the dynamically typed value.
+
+data TypeRep
+ = App TyCon [TypeRep]
+ | Fun TypeRep TypeRep
+ deriving ( Eq )
+
+-- type constructors are
+data TyCon = TyCon Int String
+
+instance Eq TyCon where
+ (TyCon t1 _) == (TyCon t2 _) = t1 == t2
+\end{code}
diff --git a/libraries/base/GHC/Enum.lhs b/libraries/base/GHC/Enum.lhs
new file mode 100644
index 0000000000..3a24c55672
--- /dev/null
+++ b/libraries/base/GHC/Enum.lhs
@@ -0,0 +1,414 @@
+% -----------------------------------------------------------------------------
+% $Id: Enum.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1992-2000
+%
+
+\section[GHC.Bounded]{Module @GHC.Bounded@}
+
+Instances of Bounded for various datatypes.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Enum(
+ Bounded(..), Enum(..),
+ boundedEnumFrom, boundedEnumFromThen,
+
+ -- Instances for Bounded and Eum: (), Char, Int
+
+ ) where
+
+import {-# SOURCE #-} GHC.Err ( error )
+import GHC.Base
+import GHC.Tup () -- To make sure we look for the .hi file
+
+default () -- Double isn't available yet
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Class declarations}
+%* *
+%*********************************************************
+
+\begin{code}
+class Bounded a where
+ minBound, maxBound :: a
+
+class Enum a where
+ succ, pred :: a -> a
+ toEnum :: Int -> a
+ fromEnum :: a -> Int
+ enumFrom :: a -> [a] -- [n..]
+ enumFromThen :: a -> a -> [a] -- [n,n'..]
+ enumFromTo :: a -> a -> [a] -- [n..m]
+ enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
+
+ succ = toEnum . (`plusInt` oneInt) . fromEnum
+ pred = toEnum . (`minusInt` oneInt) . fromEnum
+ enumFrom x = map toEnum [fromEnum x ..]
+ enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]
+ enumFromTo x y = map toEnum [fromEnum x .. fromEnum y]
+ enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
+
+-- Default methods for bounded enumerations
+boundedEnumFrom :: (Enum a, Bounded a) => a -> [a]
+boundedEnumFrom n = map toEnum [fromEnum n .. fromEnum (maxBound `asTypeOf` n)]
+
+boundedEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]
+boundedEnumFromThen n1 n2
+ | i_n2 >= i_n1 = map toEnum [i_n1, i_n2 .. fromEnum (maxBound `asTypeOf` n1)]
+ | otherwise = map toEnum [i_n1, i_n2 .. fromEnum (minBound `asTypeOf` n1)]
+ where
+ i_n1 = fromEnum n1
+ i_n2 = fromEnum n2
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Tuples}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Bounded () where
+ minBound = ()
+ maxBound = ()
+
+instance Enum () where
+ succ _ = error "Prelude.Enum.().succ: bad argment"
+ pred _ = error "Prelude.Enum.().pred: bad argument"
+
+ toEnum x | x == zeroInt = ()
+ | otherwise = error "Prelude.Enum.().toEnum: bad argument"
+
+ fromEnum () = zeroInt
+ enumFrom () = [()]
+ enumFromThen () () = [()]
+ enumFromTo () () = [()]
+ enumFromThenTo () () () = [()]
+\end{code}
+
+\begin{code}
+instance (Bounded a, Bounded b) => Bounded (a,b) where
+ minBound = (minBound, minBound)
+ maxBound = (maxBound, maxBound)
+
+instance (Bounded a, Bounded b, Bounded c) => Bounded (a,b,c) where
+ minBound = (minBound, minBound, minBound)
+ maxBound = (maxBound, maxBound, maxBound)
+
+instance (Bounded a, Bounded b, Bounded c, Bounded d) => Bounded (a,b,c,d) where
+ minBound = (minBound, minBound, minBound, minBound)
+ maxBound = (maxBound, maxBound, maxBound, maxBound)
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Type @Bool@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Bounded Bool where
+ minBound = False
+ maxBound = True
+
+instance Enum Bool where
+ succ False = True
+ succ True = error "Prelude.Enum.Bool.succ: bad argment"
+
+ pred True = False
+ pred False = error "Prelude.Enum.Bool.pred: bad argment"
+
+ toEnum n | n == zeroInt = False
+ | n == oneInt = True
+ | otherwise = error "Prelude.Enum.Bool.toEnum: bad argment"
+
+ fromEnum False = zeroInt
+ fromEnum True = oneInt
+
+ -- Use defaults for the rest
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Type @Ordering@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Bounded Ordering where
+ minBound = LT
+ maxBound = GT
+
+instance Enum Ordering where
+ succ LT = EQ
+ succ EQ = GT
+ succ GT = error "Prelude.Enum.Ordering.succ: bad argment"
+
+ pred GT = EQ
+ pred EQ = LT
+ pred LT = error "Prelude.Enum.Ordering.pred: bad argment"
+
+ toEnum n | n == zeroInt = LT
+ | n == oneInt = EQ
+ | n == twoInt = GT
+ toEnum _ = error "Prelude.Enum.Ordering.toEnum: bad argment"
+
+ fromEnum LT = zeroInt
+ fromEnum EQ = oneInt
+ fromEnum GT = twoInt
+
+ -- Use defaults for the rest
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Type @Char@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Bounded Char where
+ minBound = '\0'
+ maxBound = '\x10FFFF'
+
+instance Enum Char where
+ succ (C# c#)
+ | not (ord# c# ==# 0x10FFFF#) = C# (chr# (ord# c# +# 1#))
+ | otherwise = error ("Prelude.Enum.Char.succ: bad argument")
+ pred (C# c#)
+ | not (ord# c# ==# 0#) = C# (chr# (ord# c# -# 1#))
+ | otherwise = error ("Prelude.Enum.Char.pred: bad argument")
+
+ toEnum = chr
+ fromEnum = ord
+
+ {-# INLINE enumFrom #-}
+ enumFrom (C# x) = eftChar (ord# x) 0x10FFFF#
+ -- Blarg: technically I guess enumFrom isn't strict!
+
+ {-# INLINE enumFromTo #-}
+ enumFromTo (C# x) (C# y) = eftChar (ord# x) (ord# y)
+
+ {-# INLINE enumFromThen #-}
+ enumFromThen (C# x1) (C# x2) = efdChar (ord# x1) (ord# x2)
+
+ {-# INLINE enumFromThenTo #-}
+ enumFromThenTo (C# x1) (C# x2) (C# y) = efdtChar (ord# x1) (ord# x2) (ord# y)
+
+eftChar = eftCharList
+efdChar = efdCharList
+efdtChar = efdtCharList
+
+
+{-# RULES
+"eftChar" forall x y. eftChar x y = build (\c n -> eftCharFB c n x y)
+"efdChar" forall x1 x2. efdChar x1 x2 = build (\ c n -> efdCharFB c n x1 x2)
+"efdtChar" forall x1 x2 l. efdtChar x1 x2 l = build (\ c n -> efdtCharFB c n x1 x2 l)
+"eftCharList" eftCharFB (:) [] = eftCharList
+"efdCharList" efdCharFB (:) [] = efdCharList
+"efdtCharList" efdtCharFB (:) [] = efdtCharList
+ #-}
+
+
+-- We can do better than for Ints because we don't
+-- have hassles about arithmetic overflow at maxBound
+{-# INLINE eftCharFB #-}
+eftCharFB c n x y = go x
+ where
+ go x | x ># y = n
+ | otherwise = C# (chr# x) `c` go (x +# 1#)
+
+eftCharList x y | x ># y = []
+ | otherwise = C# (chr# x) : eftCharList (x +# 1#) y
+
+
+-- For enumFromThenTo we give up on inlining
+efdCharFB c n x1 x2
+ | delta >=# 0# = go_up_char_fb c n x1 delta 0x10FFFF#
+ | otherwise = go_dn_char_fb c n x1 delta 0#
+ where
+ delta = x2 -# x1
+
+efdCharList x1 x2
+ | delta >=# 0# = go_up_char_list x1 delta 0x10FFFF#
+ | otherwise = go_dn_char_list x1 delta 0#
+ where
+ delta = x2 -# x1
+
+efdtCharFB c n x1 x2 lim
+ | delta >=# 0# = go_up_char_fb c n x1 delta lim
+ | otherwise = go_dn_char_fb c n x1 delta lim
+ where
+ delta = x2 -# x1
+
+efdtCharList x1 x2 lim
+ | delta >=# 0# = go_up_char_list x1 delta lim
+ | otherwise = go_dn_char_list x1 delta lim
+ where
+ delta = x2 -# x1
+
+go_up_char_fb c n x delta lim
+ = go_up x
+ where
+ go_up x | x ># lim = n
+ | otherwise = C# (chr# x) `c` go_up (x +# delta)
+
+go_dn_char_fb c n x delta lim
+ = go_dn x
+ where
+ go_dn x | x <# lim = n
+ | otherwise = C# (chr# x) `c` go_dn (x +# delta)
+
+go_up_char_list x delta lim
+ = go_up x
+ where
+ go_up x | x ># lim = []
+ | otherwise = C# (chr# x) : go_up (x +# delta)
+
+go_dn_char_list x delta lim
+ = go_dn x
+ where
+ go_dn x | x <# lim = []
+ | otherwise = C# (chr# x) : go_dn (x +# delta)
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Type @Int@}
+%* *
+%*********************************************************
+
+Be careful about these instances.
+ (a) remember that you have to count down as well as up e.g. [13,12..0]
+ (b) be careful of Int overflow
+ (c) remember that Int is bounded, so [1..] terminates at maxInt
+
+Also NB that the Num class isn't available in this module.
+
+\begin{code}
+instance Bounded Int where
+ minBound = minInt
+ maxBound = maxInt
+
+instance Enum Int where
+ succ x
+ | x == maxBound = error "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"
+ | otherwise = x `plusInt` oneInt
+ pred x
+ | x == minBound = error "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"
+ | otherwise = x `minusInt` oneInt
+
+ toEnum x = x
+ fromEnum x = x
+
+ {-# INLINE enumFrom #-}
+ enumFrom (I# x) = eftInt x 2147483647#
+ -- Blarg: technically I guess enumFrom isn't strict!
+
+ {-# INLINE enumFromTo #-}
+ enumFromTo (I# x) (I# y) = eftInt x y
+
+ {-# INLINE enumFromThen #-}
+ enumFromThen (I# x1) (I# x2) = efdInt x1 x2
+
+ {-# INLINE enumFromThenTo #-}
+ enumFromThenTo (I# x1) (I# x2) (I# y) = efdtInt x1 x2 y
+
+eftInt = eftIntList
+efdInt = efdIntList
+efdtInt = efdtIntList
+
+{-# RULES
+"eftInt" forall x y. eftInt x y = build (\ c n -> eftIntFB c n x y)
+"efdInt" forall x1 x2. efdInt x1 x2 = build (\ c n -> efdIntFB c n x1 x2)
+"efdtInt" forall x1 x2 l. efdtInt x1 x2 l = build (\ c n -> efdtIntFB c n x1 x2 l)
+
+"eftIntList" eftIntFB (:) [] = eftIntList
+"efdIntList" efdIntFB (:) [] = efdIntList
+"efdtIntList" efdtIntFB (:) [] = efdtIntList
+ #-}
+
+
+{-# INLINE eftIntFB #-}
+eftIntFB c n x y | x ># y = n
+ | otherwise = go x
+ where
+ go x = I# x `c` if x ==# y then n else go (x +# 1#)
+ -- Watch out for y=maxBound; hence ==, not >
+ -- Be very careful not to have more than one "c"
+ -- so that when eftInfFB is inlined we can inline
+ -- whatver is bound to "c"
+
+eftIntList x y | x ># y = []
+ | otherwise = go x
+ where
+ go x = I# x : if x ==# y then [] else go (x +# 1#)
+
+
+-- For enumFromThenTo we give up on inlining; so we don't worry
+-- about duplicating occurrences of "c"
+efdtIntFB c n x1 x2 y
+ | delta >=# 0# = if x1 ># y then n else go_up_int_fb c n x1 delta lim
+ | otherwise = if x1 <# y then n else go_dn_int_fb c n x1 delta lim
+ where
+ delta = x2 -# x1
+ lim = y -# delta
+
+efdtIntList x1 x2 y
+ | delta >=# 0# = if x1 ># y then [] else go_up_int_list x1 delta lim
+ | otherwise = if x1 <# y then [] else go_dn_int_list x1 delta lim
+ where
+ delta = x2 -# x1
+ lim = y -# delta
+
+efdIntFB c n x1 x2
+ | delta >=# 0# = go_up_int_fb c n x1 delta ( 2147483647# -# delta)
+ | otherwise = go_dn_int_fb c n x1 delta ((-2147483648#) -# delta)
+ where
+ delta = x2 -# x1
+
+efdIntList x1 x2
+ | delta >=# 0# = go_up_int_list x1 delta ( 2147483647# -# delta)
+ | otherwise = go_dn_int_list x1 delta ((-2147483648#) -# delta)
+ where
+ delta = x2 -# x1
+
+-- In all of these, the (x +# delta) is guaranteed not to overflow
+
+go_up_int_fb c n x delta lim
+ = go_up x
+ where
+ go_up x | x ># lim = I# x `c` n
+ | otherwise = I# x `c` go_up (x +# delta)
+
+go_dn_int_fb c n x delta lim
+ = go_dn x
+ where
+ go_dn x | x <# lim = I# x `c` n
+ | otherwise = I# x `c` go_dn (x +# delta)
+
+go_up_int_list x delta lim
+ = go_up x
+ where
+ go_up x | x ># lim = [I# x]
+ | otherwise = I# x : go_up (x +# delta)
+
+go_dn_int_list x delta lim
+ = go_dn x
+ where
+ go_dn x | x <# lim = [I# x]
+ | otherwise = I# x : go_dn (x +# delta)
+\end{code}
+
diff --git a/libraries/base/GHC/Err.hi-boot b/libraries/base/GHC/Err.hi-boot
new file mode 100644
index 0000000000..258f46e367
--- /dev/null
+++ b/libraries/base/GHC/Err.hi-boot
@@ -0,0 +1,12 @@
+---------------------------------------------------------------------------
+-- PrelErr.hi-boot
+--
+-- This hand-written interface file is the initial bootstrap version
+-- for PrelErr.hi.
+-- It doesn't need to give "error" a type signature,
+-- because it's wired into the compiler
+---------------------------------------------------------------------------
+
+__interface "std" GHCziErr 1 where
+__export GHCziErr error parError;
+
diff --git a/libraries/base/GHC/Err.lhs b/libraries/base/GHC/Err.lhs
new file mode 100644
index 0000000000..c1aa78fa4f
--- /dev/null
+++ b/libraries/base/GHC/Err.lhs
@@ -0,0 +1,129 @@
+% -----------------------------------------------------------------------------
+% $Id: Err.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Err]{Module @GHC.Err@}
+
+The GHC.Err module defines the code for the wired-in error functions,
+which have a special type in the compiler (with "open tyvars").
+
+We cannot define these functions in a module where they might be used
+(e.g., GHC.Base), because the magical wired-in type will get confused
+with what the typechecker figures out.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+module GHC.Err
+ (
+ irrefutPatError
+ , noMethodBindingError
+ , nonExhaustiveGuardsError
+ , patError
+ , recSelError
+ , recConError
+ , recUpdError -- :: String -> a
+
+ , absentErr, parError -- :: a
+ , seqError -- :: a
+
+ , error -- :: String -> a
+ , assertError -- :: String -> Bool -> a -> a
+
+ , undefined -- :: a
+ ) where
+
+import GHC.Base
+import GHC.List ( span )
+import GHC.Exception
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Error-ish functions}
+%* *
+%*********************************************************
+
+\begin{code}
+-- error stops execution and displays an error message
+error :: String -> a
+error s = throw (ErrorCall s)
+
+-- It is expected that compilers will recognize this and insert error
+-- messages which are more appropriate to the context in which undefined
+-- appears.
+
+undefined :: a
+undefined = error "Prelude.undefined"
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Compiler generated errors + local utils}
+%* *
+%*********************************************************
+
+Used for compiler-generated error message;
+encoding saves bytes of string junk.
+
+\begin{code}
+absentErr, parError, seqError :: a
+
+absentErr = error "Oops! The program has entered an `absent' argument!\n"
+parError = error "Oops! Entered GHCerr.parError (a GHC bug -- please report it!)\n"
+seqError = error "Oops! Entered seqError (a GHC bug -- please report it!)\n"
+
+\end{code}
+
+\begin{code}
+irrefutPatError
+ , noMethodBindingError
+ , nonExhaustiveGuardsError
+ , patError
+ , recSelError
+ , recConError
+ , recUpdError :: String -> a
+
+noMethodBindingError s = throw (NoMethodError (untangle s "No instance nor default method for class operation"))
+irrefutPatError s = throw (PatternMatchFail (untangle s "Irrefutable pattern failed for pattern"))
+nonExhaustiveGuardsError s = throw (PatternMatchFail (untangle s "Non-exhaustive guards in"))
+patError s = throw (PatternMatchFail (untangle s "Non-exhaustive patterns in"))
+recSelError s = throw (RecSelError (untangle s "Missing field in record selection"))
+recConError s = throw (RecConError (untangle s "Missing field in record construction"))
+recUpdError s = throw (RecUpdError (untangle s "Record doesn't contain field(s) to be updated"))
+
+
+assertError :: String -> Bool -> a -> a
+assertError str pred v
+ | pred = v
+ | otherwise = throw (AssertionFailed (untangle str "Assertion failed"))
+
+\end{code}
+
+
+(untangle coded message) expects "coded" to be of the form
+
+ "location|details"
+
+It prints
+
+ location message details
+
+\begin{code}
+untangle :: String -> String -> String
+untangle coded message
+ = location
+ ++ ": "
+ ++ message
+ ++ details
+ ++ "\n"
+ where
+ (location, details)
+ = case (span not_bar coded) of { (loc, rest) ->
+ case rest of
+ ('|':det) -> (loc, ' ' : det)
+ _ -> (loc, "")
+ }
+ not_bar c = c /= '|'
+\end{code}
diff --git a/libraries/base/GHC/Exception.lhs b/libraries/base/GHC/Exception.lhs
new file mode 100644
index 0000000000..abf9a82938
--- /dev/null
+++ b/libraries/base/GHC/Exception.lhs
@@ -0,0 +1,123 @@
+% ------------------------------------------------------------------------------
+% $Id: Exception.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1998-2000
+%
+
+Exceptions and exception-handling functions.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#ifndef __HUGS__
+module GHC.Exception
+ ( module GHC.Exception,
+ Exception(..), AsyncException(..),
+ IOException(..), ArithException(..), ArrayException(..),
+ throw, ioError )
+ where
+
+import GHC.Base
+import GHC.Maybe
+import GHC.IOBase
+
+#endif
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Primitive catch}
+%* *
+%*********************************************************
+
+catchException used to handle the passing around of the state to the
+action and the handler. This turned out to be a bad idea - it meant
+that we had to wrap both arguments in thunks so they could be entered
+as normal (remember IO returns an unboxed pair...).
+
+Now catch# has type
+
+ catch# :: IO a -> (b -> IO a) -> IO a
+
+(well almost; the compiler doesn't know about the IO newtype so we
+have to work around that in the definition of catchException below).
+
+\begin{code}
+catchException :: IO a -> (Exception -> IO a) -> IO a
+#ifdef __HUGS__
+catchException m k = ST (\s -> unST m s `primCatch'` \ err -> unST (k err) s)
+#else
+catchException (IO m) k = IO $ \s -> catch# m (\ex -> unIO (k ex)) s
+#endif
+
+catch :: IO a -> (Exception -> IO a) -> IO a
+catch m k = catchException m handler
+ where handler err@(IOException _) = k err
+ handler err@(UserError _) = k err
+ handler other = throw other
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Try and bracket}
+%* *
+%*********************************************************
+
+The construct @try comp@ exposes errors which occur within a
+computation, and which are not fully handled. It always succeeds.
+
+These are the IO-only try/bracket. For the full exception try/bracket
+see hslibs/lang/Exception.lhs.
+
+\begin{code}
+try :: IO a -> IO (Either Exception a)
+try f = catch (do r <- f
+ return (Right r))
+ (return . Left)
+
+bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+bracket before after m = do
+ x <- before
+ rs <- try (m x)
+ after x
+ case rs of
+ Right r -> return r
+ Left e -> ioError e
+
+-- variant of the above where middle computation doesn't want x
+bracket_ :: IO a -> (a -> IO b) -> IO c -> IO c
+bracket_ before after m = do
+ x <- before
+ rs <- try m
+ after x
+ case rs of
+ Right r -> return r
+ Left e -> ioError e
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Controlling asynchronous exception delivery}
+%* *
+%*********************************************************
+
+\begin{code}
+#ifndef __HUGS__
+block :: IO a -> IO a
+block (IO io) = IO $ blockAsyncExceptions# io
+
+unblock :: IO a -> IO a
+unblock (IO io) = IO $ unblockAsyncExceptions# io
+#else
+-- Not implemented yet in Hugs.
+block :: IO a -> IO a
+block (IO io) = IO io
+
+unblock :: IO a -> IO a
+unblock (IO io) = IO io
+#endif
+\end{code}
+
+
diff --git a/libraries/base/GHC/Float.lhs b/libraries/base/GHC/Float.lhs
new file mode 100644
index 0000000000..186d29c427
--- /dev/null
+++ b/libraries/base/GHC/Float.lhs
@@ -0,0 +1,892 @@
+% ------------------------------------------------------------------------------
+% $Id: Float.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Num]{Module @GHC.Num@}
+
+The types
+
+ Float
+ Double
+
+and the classes
+
+ Floating
+ RealFloat
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#include "ieee-flpt.h"
+
+module GHC.Float( module GHC.Float, Float#, Double# ) where
+
+import GHC.Base
+import GHC.List
+import GHC.Enum
+import GHC.Show
+import GHC.Num
+import GHC.Real
+import GHC.Arr
+import GHC.Maybe
+
+infixr 8 **
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Standard numeric classes}
+%* *
+%*********************************************************
+
+\begin{code}
+class (Fractional a) => Floating a where
+ pi :: a
+ exp, log, sqrt :: a -> a
+ (**), logBase :: a -> a -> a
+ sin, cos, tan :: a -> a
+ asin, acos, atan :: a -> a
+ sinh, cosh, tanh :: a -> a
+ asinh, acosh, atanh :: a -> a
+
+ x ** y = exp (log x * y)
+ logBase x y = log y / log x
+ sqrt x = x ** 0.5
+ tan x = sin x / cos x
+ tanh x = sinh x / cosh x
+
+class (RealFrac a, Floating a) => RealFloat a where
+ floatRadix :: a -> Integer
+ floatDigits :: a -> Int
+ floatRange :: a -> (Int,Int)
+ decodeFloat :: a -> (Integer,Int)
+ encodeFloat :: Integer -> Int -> a
+ exponent :: a -> Int
+ significand :: a -> a
+ scaleFloat :: Int -> a -> a
+ isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE
+ :: a -> Bool
+ atan2 :: a -> a -> a
+
+
+ exponent x = if m == 0 then 0 else n + floatDigits x
+ where (m,n) = decodeFloat x
+
+ significand x = encodeFloat m (negate (floatDigits x))
+ where (m,_) = decodeFloat x
+
+ scaleFloat k x = encodeFloat m (n+k)
+ where (m,n) = decodeFloat x
+
+ atan2 y x
+ | x > 0 = atan (y/x)
+ | x == 0 && y > 0 = pi/2
+ | x < 0 && y > 0 = pi + atan (y/x)
+ |(x <= 0 && y < 0) ||
+ (x < 0 && isNegativeZero y) ||
+ (isNegativeZero x && isNegativeZero y)
+ = -atan2 (-y) x
+ | y == 0 && (x < 0 || isNegativeZero x)
+ = pi -- must be after the previous test on zero y
+ | x==0 && y==0 = y -- must be after the other double zero tests
+ | otherwise = x + y -- x or y is a NaN, return a NaN (via +)
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Type @Integer@, @Float@, @Double@}
+%* *
+%*********************************************************
+
+\begin{code}
+data Float = F# Float#
+data Double = D# Double#
+
+instance CCallable Float
+instance CReturnable Float
+
+instance CCallable Double
+instance CReturnable Double
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Type @Float@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Eq Float where
+ (F# x) == (F# y) = x `eqFloat#` y
+
+instance Ord Float where
+ (F# x) `compare` (F# y) | x `ltFloat#` y = LT
+ | x `eqFloat#` y = EQ
+ | otherwise = GT
+
+ (F# x) < (F# y) = x `ltFloat#` y
+ (F# x) <= (F# y) = x `leFloat#` y
+ (F# x) >= (F# y) = x `geFloat#` y
+ (F# x) > (F# y) = x `gtFloat#` y
+
+instance Num Float where
+ (+) x y = plusFloat x y
+ (-) x y = minusFloat x y
+ negate x = negateFloat x
+ (*) x y = timesFloat x y
+ abs x | x >= 0.0 = x
+ | otherwise = negateFloat x
+ signum x | x == 0.0 = 0
+ | x > 0.0 = 1
+ | otherwise = negate 1
+
+ {-# INLINE fromInteger #-}
+ fromInteger n = encodeFloat n 0
+ -- It's important that encodeFloat inlines here, and that
+ -- fromInteger in turn inlines,
+ -- so that if fromInteger is applied to an (S# i) the right thing happens
+
+instance Real Float where
+ toRational x = (m%1)*(b%1)^^n
+ where (m,n) = decodeFloat x
+ b = floatRadix x
+
+instance Fractional Float where
+ (/) x y = divideFloat x y
+ fromRational x = fromRat x
+ recip x = 1.0 / x
+
+{-# RULES "truncate/Float->Int" truncate = float2Int #-}
+instance RealFrac Float where
+
+ {-# SPECIALIZE properFraction :: Float -> (Int, Float) #-}
+ {-# SPECIALIZE round :: Float -> Int #-}
+ {-# SPECIALIZE ceiling :: Float -> Int #-}
+ {-# SPECIALIZE floor :: Float -> Int #-}
+
+ {-# SPECIALIZE properFraction :: Float -> (Integer, Float) #-}
+ {-# SPECIALIZE truncate :: Float -> Integer #-}
+ {-# SPECIALIZE round :: Float -> Integer #-}
+ {-# SPECIALIZE ceiling :: Float -> Integer #-}
+ {-# SPECIALIZE floor :: Float -> Integer #-}
+
+ properFraction x
+ = case (decodeFloat x) of { (m,n) ->
+ let b = floatRadix x in
+ if n >= 0 then
+ (fromInteger m * fromInteger b ^ n, 0.0)
+ else
+ case (quotRem m (b^(negate n))) of { (w,r) ->
+ (fromInteger w, encodeFloat r n)
+ }
+ }
+
+ truncate x = case properFraction x of
+ (n,_) -> n
+
+ round x = case properFraction x of
+ (n,r) -> let
+ m = if r < 0.0 then n - 1 else n + 1
+ half_down = abs r - 0.5
+ in
+ case (compare half_down 0.0) of
+ LT -> n
+ EQ -> if even n then n else m
+ GT -> m
+
+ ceiling x = case properFraction x of
+ (n,r) -> if r > 0.0 then n + 1 else n
+
+ floor x = case properFraction x of
+ (n,r) -> if r < 0.0 then n - 1 else n
+
+instance Floating Float where
+ pi = 3.141592653589793238
+ exp x = expFloat x
+ log x = logFloat x
+ sqrt x = sqrtFloat x
+ sin x = sinFloat x
+ cos x = cosFloat x
+ tan x = tanFloat x
+ asin x = asinFloat x
+ acos x = acosFloat x
+ atan x = atanFloat x
+ sinh x = sinhFloat x
+ cosh x = coshFloat x
+ tanh x = tanhFloat x
+ (**) x y = powerFloat x y
+ logBase x y = log y / log x
+
+ asinh x = log (x + sqrt (1.0+x*x))
+ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))
+ atanh x = log ((x+1.0) / sqrt (1.0-x*x))
+
+instance RealFloat Float where
+ floatRadix _ = FLT_RADIX -- from float.h
+ floatDigits _ = FLT_MANT_DIG -- ditto
+ floatRange _ = (FLT_MIN_EXP, FLT_MAX_EXP) -- ditto
+
+ decodeFloat (F# f#)
+ = case decodeFloat# f# of
+ (# exp#, s#, d# #) -> (J# s# d#, I# exp#)
+
+ encodeFloat (S# i) j = int_encodeFloat# i j
+ encodeFloat (J# s# d#) e = encodeFloat# s# d# e
+
+ exponent x = case decodeFloat x of
+ (m,n) -> if m == 0 then 0 else n + floatDigits x
+
+ significand x = case decodeFloat x of
+ (m,_) -> encodeFloat m (negate (floatDigits x))
+
+ scaleFloat k x = case decodeFloat x of
+ (m,n) -> encodeFloat m (n+k)
+ isNaN x = 0 /= isFloatNaN x
+ isInfinite x = 0 /= isFloatInfinite x
+ isDenormalized x = 0 /= isFloatDenormalized x
+ isNegativeZero x = 0 /= isFloatNegativeZero x
+ isIEEE _ = True
+
+instance Show Float where
+ showsPrec x = showSigned showFloat x
+ showList = showList__ (showsPrec 0)
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Type @Double@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Eq Double where
+ (D# x) == (D# y) = x ==## y
+
+instance Ord Double where
+ (D# x) `compare` (D# y) | x <## y = LT
+ | x ==## y = EQ
+ | otherwise = GT
+
+ (D# x) < (D# y) = x <## y
+ (D# x) <= (D# y) = x <=## y
+ (D# x) >= (D# y) = x >=## y
+ (D# x) > (D# y) = x >## y
+
+instance Num Double where
+ (+) x y = plusDouble x y
+ (-) x y = minusDouble x y
+ negate x = negateDouble x
+ (*) x y = timesDouble x y
+ abs x | x >= 0.0 = x
+ | otherwise = negateDouble x
+ signum x | x == 0.0 = 0
+ | x > 0.0 = 1
+ | otherwise = negate 1
+
+ {-# INLINE fromInteger #-}
+ -- See comments with Num Float
+ fromInteger (S# i#) = case (int2Double# i#) of { d# -> D# d# }
+ fromInteger (J# s# d#) = encodeDouble# s# d# 0
+
+
+instance Real Double where
+ toRational x = (m%1)*(b%1)^^n
+ where (m,n) = decodeFloat x
+ b = floatRadix x
+
+instance Fractional Double where
+ (/) x y = divideDouble x y
+ fromRational x = fromRat x
+ recip x = 1.0 / x
+
+instance Floating Double where
+ pi = 3.141592653589793238
+ exp x = expDouble x
+ log x = logDouble x
+ sqrt x = sqrtDouble x
+ sin x = sinDouble x
+ cos x = cosDouble x
+ tan x = tanDouble x
+ asin x = asinDouble x
+ acos x = acosDouble x
+ atan x = atanDouble x
+ sinh x = sinhDouble x
+ cosh x = coshDouble x
+ tanh x = tanhDouble x
+ (**) x y = powerDouble x y
+ logBase x y = log y / log x
+
+ asinh x = log (x + sqrt (1.0+x*x))
+ acosh x = log (x + (x+1.0) * sqrt ((x-1.0)/(x+1.0)))
+ atanh x = log ((x+1.0) / sqrt (1.0-x*x))
+
+{-# RULES "truncate/Double->Int" truncate = double2Int #-}
+instance RealFrac Double where
+
+ {-# SPECIALIZE properFraction :: Double -> (Int, Double) #-}
+ {-# SPECIALIZE round :: Double -> Int #-}
+ {-# SPECIALIZE ceiling :: Double -> Int #-}
+ {-# SPECIALIZE floor :: Double -> Int #-}
+
+ {-# SPECIALIZE properFraction :: Double -> (Integer, Double) #-}
+ {-# SPECIALIZE truncate :: Double -> Integer #-}
+ {-# SPECIALIZE round :: Double -> Integer #-}
+ {-# SPECIALIZE ceiling :: Double -> Integer #-}
+ {-# SPECIALIZE floor :: Double -> Integer #-}
+
+ properFraction x
+ = case (decodeFloat x) of { (m,n) ->
+ let b = floatRadix x in
+ if n >= 0 then
+ (fromInteger m * fromInteger b ^ n, 0.0)
+ else
+ case (quotRem m (b^(negate n))) of { (w,r) ->
+ (fromInteger w, encodeFloat r n)
+ }
+ }
+
+ truncate x = case properFraction x of
+ (n,_) -> n
+
+ round x = case properFraction x of
+ (n,r) -> let
+ m = if r < 0.0 then n - 1 else n + 1
+ half_down = abs r - 0.5
+ in
+ case (compare half_down 0.0) of
+ LT -> n
+ EQ -> if even n then n else m
+ GT -> m
+
+ ceiling x = case properFraction x of
+ (n,r) -> if r > 0.0 then n + 1 else n
+
+ floor x = case properFraction x of
+ (n,r) -> if r < 0.0 then n - 1 else n
+
+instance RealFloat Double where
+ floatRadix _ = FLT_RADIX -- from float.h
+ floatDigits _ = DBL_MANT_DIG -- ditto
+ floatRange _ = (DBL_MIN_EXP, DBL_MAX_EXP) -- ditto
+
+ decodeFloat (D# x#)
+ = case decodeDouble# x# of
+ (# exp#, s#, d# #) -> (J# s# d#, I# exp#)
+
+ encodeFloat (S# i) j = int_encodeDouble# i j
+ encodeFloat (J# s# d#) e = encodeDouble# s# d# e
+
+ exponent x = case decodeFloat x of
+ (m,n) -> if m == 0 then 0 else n + floatDigits x
+
+ significand x = case decodeFloat x of
+ (m,_) -> encodeFloat m (negate (floatDigits x))
+
+ scaleFloat k x = case decodeFloat x of
+ (m,n) -> encodeFloat m (n+k)
+
+ isNaN x = 0 /= isDoubleNaN x
+ isInfinite x = 0 /= isDoubleInfinite x
+ isDenormalized x = 0 /= isDoubleDenormalized x
+ isNegativeZero x = 0 /= isDoubleNegativeZero x
+ isIEEE _ = True
+
+instance Show Double where
+ showsPrec x = showSigned showFloat x
+ showList = showList__ (showsPrec 0)
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{@Enum@ instances}
+%* *
+%*********************************************************
+
+The @Enum@ instances for Floats and Doubles are slightly unusual.
+The @toEnum@ function truncates numbers to Int. The definitions
+of @enumFrom@ and @enumFromThen@ allow floats to be used in arithmetic
+series: [0,0.1 .. 1.0]. However, roundoff errors make these somewhat
+dubious. This example may have either 10 or 11 elements, depending on
+how 0.1 is represented.
+
+NOTE: The instances for Float and Double do not make use of the default
+methods for @enumFromTo@ and @enumFromThenTo@, as these rely on there being
+a `non-lossy' conversion to and from Ints. Instead we make use of the
+1.2 default methods (back in the days when Enum had Ord as a superclass)
+for these (@numericEnumFromTo@ and @numericEnumFromThenTo@ below.)
+
+\begin{code}
+instance Enum Float where
+ succ x = x + 1
+ pred x = x - 1
+ toEnum = int2Float
+ fromEnum = fromInteger . truncate -- may overflow
+ enumFrom = numericEnumFrom
+ enumFromTo = numericEnumFromTo
+ enumFromThen = numericEnumFromThen
+ enumFromThenTo = numericEnumFromThenTo
+
+instance Enum Double where
+ succ x = x + 1
+ pred x = x - 1
+ toEnum = int2Double
+ fromEnum = fromInteger . truncate -- may overflow
+ enumFrom = numericEnumFrom
+ enumFromTo = numericEnumFromTo
+ enumFromThen = numericEnumFromThen
+ enumFromThenTo = numericEnumFromThenTo
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Printing floating point}
+%* *
+%*********************************************************
+
+
+\begin{code}
+showFloat :: (RealFloat a) => a -> ShowS
+showFloat x = showString (formatRealFloat FFGeneric Nothing x)
+
+-- These are the format types. This type is not exported.
+
+data FFFormat = FFExponent | FFFixed | FFGeneric
+
+formatRealFloat :: (RealFloat a) => FFFormat -> Maybe Int -> a -> String
+formatRealFloat fmt decs x
+ | isNaN x = "NaN"
+ | isInfinite x = if x < 0 then "-Infinity" else "Infinity"
+ | x < 0 || isNegativeZero x = '-':doFmt fmt (floatToDigits (toInteger base) (-x))
+ | otherwise = doFmt fmt (floatToDigits (toInteger base) x)
+ where
+ base = 10
+
+ doFmt format (is, e) =
+ let ds = map intToDigit is in
+ case format of
+ FFGeneric ->
+ doFmt (if e < 0 || e > 7 then FFExponent else FFFixed)
+ (is,e)
+ FFExponent ->
+ case decs of
+ Nothing ->
+ let show_e' = show (e-1) in
+ case ds of
+ "0" -> "0.0e0"
+ [d] -> d : ".0e" ++ show_e'
+ (d:ds') -> d : '.' : ds' ++ "e" ++ show_e'
+ Just dec ->
+ let dec' = max dec 1 in
+ case is of
+ [0] -> '0' :'.' : take dec' (repeat '0') ++ "e0"
+ _ ->
+ let
+ (ei,is') = roundTo base (dec'+1) is
+ (d:ds') = map intToDigit (if ei > 0 then init is' else is')
+ in
+ d:'.':ds' ++ 'e':show (e-1+ei)
+ FFFixed ->
+ let
+ mk0 ls = case ls of { "" -> "0" ; _ -> ls}
+ in
+ case decs of
+ Nothing ->
+ let
+ f 0 s rs = mk0 (reverse s) ++ '.':mk0 rs
+ f n s "" = f (n-1) ('0':s) ""
+ f n s (r:rs) = f (n-1) (r:s) rs
+ in
+ f e "" ds
+ Just dec ->
+ let dec' = max dec 0 in
+ if e >= 0 then
+ let
+ (ei,is') = roundTo base (dec' + e) is
+ (ls,rs) = splitAt (e+ei) (map intToDigit is')
+ in
+ mk0 ls ++ (if null rs then "" else '.':rs)
+ else
+ let
+ (ei,is') = roundTo base dec' (replicate (-e) 0 ++ is)
+ d:ds' = map intToDigit (if ei > 0 then is' else 0:is')
+ in
+ d : '.' : ds'
+
+
+roundTo :: Int -> Int -> [Int] -> (Int,[Int])
+roundTo base d is =
+ case f d is of
+ x@(0,_) -> x
+ (1,xs) -> (1, 1:xs)
+ where
+ b2 = base `div` 2
+
+ f n [] = (0, replicate n 0)
+ f 0 (x:_) = (if x >= b2 then 1 else 0, [])
+ f n (i:xs)
+ | i' == base = (1,0:ds)
+ | otherwise = (0,i':ds)
+ where
+ (c,ds) = f (n-1) xs
+ i' = c + i
+
+--
+-- Based on "Printing Floating-Point Numbers Quickly and Accurately"
+-- by R.G. Burger and R.K. Dybvig in PLDI 96.
+-- This version uses a much slower logarithm estimator. It should be improved.
+
+-- This function returns a list of digits (Ints in [0..base-1]) and an
+-- exponent.
+
+floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int)
+floatToDigits _ 0 = ([0], 0)
+floatToDigits base x =
+ let
+ (f0, e0) = decodeFloat x
+ (minExp0, _) = floatRange x
+ p = floatDigits x
+ b = floatRadix x
+ minExp = minExp0 - p -- the real minimum exponent
+ -- Haskell requires that f be adjusted so denormalized numbers
+ -- will have an impossibly low exponent. Adjust for this.
+ (f, e) =
+ let n = minExp - e0 in
+ if n > 0 then (f0 `div` (b^n), e0+n) else (f0, e0)
+ (r, s, mUp, mDn) =
+ if e >= 0 then
+ let be = b^ e in
+ if f == b^(p-1) then
+ (f*be*b*2, 2*b, be*b, b)
+ else
+ (f*be*2, 2, be, be)
+ else
+ if e > minExp && f == b^(p-1) then
+ (f*b*2, b^(-e+1)*2, b, 1)
+ else
+ (f*2, b^(-e)*2, 1, 1)
+ k =
+ let
+ k0 =
+ if b == 2 && base == 10 then
+ -- logBase 10 2 is slightly bigger than 3/10 so
+ -- the following will err on the low side. Ignoring
+ -- the fraction will make it err even more.
+ -- Haskell promises that p-1 <= logBase b f < p.
+ (p - 1 + e0) * 3 `div` 10
+ else
+ ceiling ((log (fromInteger (f+1)) +
+ fromInteger (int2Integer e) * log (fromInteger b)) /
+ log (fromInteger base))
+--WAS: fromInt e * log (fromInteger b))
+
+ fixup n =
+ if n >= 0 then
+ if r + mUp <= expt base n * s then n else fixup (n+1)
+ else
+ if expt base (-n) * (r + mUp) <= s then n else fixup (n+1)
+ in
+ fixup k0
+
+ gen ds rn sN mUpN mDnN =
+ let
+ (dn, rn') = (rn * base) `divMod` sN
+ mUpN' = mUpN * base
+ mDnN' = mDnN * base
+ in
+ case (rn' < mDnN', rn' + mUpN' > sN) of
+ (True, False) -> dn : ds
+ (False, True) -> dn+1 : ds
+ (True, True) -> if rn' * 2 < sN then dn : ds else dn+1 : ds
+ (False, False) -> gen (dn:ds) rn' sN mUpN' mDnN'
+
+ rds =
+ if k >= 0 then
+ gen [] r (s * expt base k) mUp mDn
+ else
+ let bk = expt base (-k) in
+ gen [] (r * bk) s (mUp * bk) (mDn * bk)
+ in
+ (map fromIntegral (reverse rds), k)
+
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Converting from a Rational to a RealFloat
+%* *
+%*********************************************************
+
+[In response to a request for documentation of how fromRational works,
+Joe Fasel writes:] A quite reasonable request! This code was added to
+the Prelude just before the 1.2 release, when Lennart, working with an
+early version of hbi, noticed that (read . show) was not the identity
+for floating-point numbers. (There was a one-bit error about half the
+time.) The original version of the conversion function was in fact
+simply a floating-point divide, as you suggest above. The new version
+is, I grant you, somewhat denser.
+
+Unfortunately, Joe's code doesn't work! Here's an example:
+
+main = putStr (shows (1.82173691287639817263897126389712638972163e-300::Double) "\n")
+
+This program prints
+ 0.0000000000000000
+instead of
+ 1.8217369128763981e-300
+
+Here's Joe's code:
+
+\begin{pseudocode}
+fromRat :: (RealFloat a) => Rational -> a
+fromRat x = x'
+ where x' = f e
+
+-- If the exponent of the nearest floating-point number to x
+-- is e, then the significand is the integer nearest xb^(-e),
+-- where b is the floating-point radix. We start with a good
+-- guess for e, and if it is correct, the exponent of the
+-- floating-point number we construct will again be e. If
+-- not, one more iteration is needed.
+
+ f e = if e' == e then y else f e'
+ where y = encodeFloat (round (x * (1 % b)^^e)) e
+ (_,e') = decodeFloat y
+ b = floatRadix x'
+
+-- We obtain a trial exponent by doing a floating-point
+-- division of x's numerator by its denominator. The
+-- result of this division may not itself be the ultimate
+-- result, because of an accumulation of three rounding
+-- errors.
+
+ (s,e) = decodeFloat (fromInteger (numerator x) `asTypeOf` x'
+ / fromInteger (denominator x))
+\end{pseudocode}
+
+Now, here's Lennart's code (which works)
+
+\begin{code}
+{-# SPECIALISE fromRat ::
+ Rational -> Double,
+ Rational -> Float #-}
+fromRat :: (RealFloat a) => Rational -> a
+fromRat x
+ | x == 0 = encodeFloat 0 0 -- Handle exceptional cases
+ | x < 0 = - fromRat' (-x) -- first.
+ | otherwise = fromRat' x
+
+-- Conversion process:
+-- Scale the rational number by the RealFloat base until
+-- it lies in the range of the mantissa (as used by decodeFloat/encodeFloat).
+-- Then round the rational to an Integer and encode it with the exponent
+-- that we got from the scaling.
+-- To speed up the scaling process we compute the log2 of the number to get
+-- a first guess of the exponent.
+
+fromRat' :: (RealFloat a) => Rational -> a
+fromRat' x = r
+ where b = floatRadix r
+ p = floatDigits r
+ (minExp0, _) = floatRange r
+ minExp = minExp0 - p -- the real minimum exponent
+ xMin = toRational (expt b (p-1))
+ xMax = toRational (expt b p)
+ p0 = (integerLogBase b (numerator x) - integerLogBase b (denominator x) - p) `max` minExp
+ f = if p0 < 0 then 1 % expt b (-p0) else expt b p0 % 1
+ (x', p') = scaleRat (toRational b) minExp xMin xMax p0 (x / f)
+ r = encodeFloat (round x') p'
+
+-- Scale x until xMin <= x < xMax, or p (the exponent) <= minExp.
+scaleRat :: Rational -> Int -> Rational -> Rational -> Int -> Rational -> (Rational, Int)
+scaleRat b minExp xMin xMax p x
+ | p <= minExp = (x, p)
+ | x >= xMax = scaleRat b minExp xMin xMax (p+1) (x/b)
+ | x < xMin = scaleRat b minExp xMin xMax (p-1) (x*b)
+ | otherwise = (x, p)
+
+-- Exponentiation with a cache for the most common numbers.
+minExpt, maxExpt :: Int
+minExpt = 0
+maxExpt = 1100
+
+expt :: Integer -> Int -> Integer
+expt base n =
+ if base == 2 && n >= minExpt && n <= maxExpt then
+ expts!n
+ else
+ base^n
+
+expts :: Array Int Integer
+expts = array (minExpt,maxExpt) [(n,2^n) | n <- [minExpt .. maxExpt]]
+
+-- Compute the (floor of the) log of i in base b.
+-- Simplest way would be just divide i by b until it's smaller then b, but that would
+-- be very slow! We are just slightly more clever.
+integerLogBase :: Integer -> Integer -> Int
+integerLogBase b i
+ | i < b = 0
+ | otherwise = doDiv (i `div` (b^l)) l
+ where
+ -- Try squaring the base first to cut down the number of divisions.
+ l = 2 * integerLogBase (b*b) i
+
+ doDiv :: Integer -> Int -> Int
+ doDiv x y
+ | x < b = y
+ | otherwise = doDiv (x `div` b) (y+1)
+
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Floating point numeric primops}
+%* *
+%*********************************************************
+
+Definitions of the boxed PrimOps; these will be
+used in the case of partial applications, etc.
+
+\begin{code}
+plusFloat, minusFloat, timesFloat, divideFloat :: Float -> Float -> Float
+plusFloat (F# x) (F# y) = F# (plusFloat# x y)
+minusFloat (F# x) (F# y) = F# (minusFloat# x y)
+timesFloat (F# x) (F# y) = F# (timesFloat# x y)
+divideFloat (F# x) (F# y) = F# (divideFloat# x y)
+
+negateFloat :: Float -> Float
+negateFloat (F# x) = F# (negateFloat# x)
+
+gtFloat, geFloat, eqFloat, neFloat, ltFloat, leFloat :: Float -> Float -> Bool
+gtFloat (F# x) (F# y) = gtFloat# x y
+geFloat (F# x) (F# y) = geFloat# x y
+eqFloat (F# x) (F# y) = eqFloat# x y
+neFloat (F# x) (F# y) = neFloat# x y
+ltFloat (F# x) (F# y) = ltFloat# x y
+leFloat (F# x) (F# y) = leFloat# x y
+
+float2Int :: Float -> Int
+float2Int (F# x) = I# (float2Int# x)
+
+int2Float :: Int -> Float
+int2Float (I# x) = F# (int2Float# x)
+
+expFloat, logFloat, sqrtFloat :: Float -> Float
+sinFloat, cosFloat, tanFloat :: Float -> Float
+asinFloat, acosFloat, atanFloat :: Float -> Float
+sinhFloat, coshFloat, tanhFloat :: Float -> Float
+expFloat (F# x) = F# (expFloat# x)
+logFloat (F# x) = F# (logFloat# x)
+sqrtFloat (F# x) = F# (sqrtFloat# x)
+sinFloat (F# x) = F# (sinFloat# x)
+cosFloat (F# x) = F# (cosFloat# x)
+tanFloat (F# x) = F# (tanFloat# x)
+asinFloat (F# x) = F# (asinFloat# x)
+acosFloat (F# x) = F# (acosFloat# x)
+atanFloat (F# x) = F# (atanFloat# x)
+sinhFloat (F# x) = F# (sinhFloat# x)
+coshFloat (F# x) = F# (coshFloat# x)
+tanhFloat (F# x) = F# (tanhFloat# x)
+
+powerFloat :: Float -> Float -> Float
+powerFloat (F# x) (F# y) = F# (powerFloat# x y)
+
+-- definitions of the boxed PrimOps; these will be
+-- used in the case of partial applications, etc.
+
+plusDouble, minusDouble, timesDouble, divideDouble :: Double -> Double -> Double
+plusDouble (D# x) (D# y) = D# (x +## y)
+minusDouble (D# x) (D# y) = D# (x -## y)
+timesDouble (D# x) (D# y) = D# (x *## y)
+divideDouble (D# x) (D# y) = D# (x /## y)
+
+negateDouble :: Double -> Double
+negateDouble (D# x) = D# (negateDouble# x)
+
+gtDouble, geDouble, eqDouble, neDouble, leDouble, ltDouble :: Double -> Double -> Bool
+gtDouble (D# x) (D# y) = x >## y
+geDouble (D# x) (D# y) = x >=## y
+eqDouble (D# x) (D# y) = x ==## y
+neDouble (D# x) (D# y) = x /=## y
+ltDouble (D# x) (D# y) = x <## y
+leDouble (D# x) (D# y) = x <=## y
+
+double2Int :: Double -> Int
+double2Int (D# x) = I# (double2Int# x)
+
+int2Double :: Int -> Double
+int2Double (I# x) = D# (int2Double# x)
+
+double2Float :: Double -> Float
+double2Float (D# x) = F# (double2Float# x)
+
+float2Double :: Float -> Double
+float2Double (F# x) = D# (float2Double# x)
+
+expDouble, logDouble, sqrtDouble :: Double -> Double
+sinDouble, cosDouble, tanDouble :: Double -> Double
+asinDouble, acosDouble, atanDouble :: Double -> Double
+sinhDouble, coshDouble, tanhDouble :: Double -> Double
+expDouble (D# x) = D# (expDouble# x)
+logDouble (D# x) = D# (logDouble# x)
+sqrtDouble (D# x) = D# (sqrtDouble# x)
+sinDouble (D# x) = D# (sinDouble# x)
+cosDouble (D# x) = D# (cosDouble# x)
+tanDouble (D# x) = D# (tanDouble# x)
+asinDouble (D# x) = D# (asinDouble# x)
+acosDouble (D# x) = D# (acosDouble# x)
+atanDouble (D# x) = D# (atanDouble# x)
+sinhDouble (D# x) = D# (sinhDouble# x)
+coshDouble (D# x) = D# (coshDouble# x)
+tanhDouble (D# x) = D# (tanhDouble# x)
+
+powerDouble :: Double -> Double -> Double
+powerDouble (D# x) (D# y) = D# (x **## y)
+\end{code}
+
+\begin{code}
+foreign import ccall "__encodeFloat" unsafe
+ encodeFloat# :: Int# -> ByteArray# -> Int -> Float
+foreign import ccall "__int_encodeFloat" unsafe
+ int_encodeFloat# :: Int# -> Int -> Float
+
+
+foreign import ccall "isFloatNaN" unsafe isFloatNaN :: Float -> Int
+foreign import ccall "isFloatInfinite" unsafe isFloatInfinite :: Float -> Int
+foreign import ccall "isFloatDenormalized" unsafe isFloatDenormalized :: Float -> Int
+foreign import ccall "isFloatNegativeZero" unsafe isFloatNegativeZero :: Float -> Int
+
+
+foreign import ccall "__encodeDouble" unsafe
+ encodeDouble# :: Int# -> ByteArray# -> Int -> Double
+foreign import ccall "__int_encodeDouble" unsafe
+ int_encodeDouble# :: Int# -> Int -> Double
+
+foreign import ccall "isDoubleNaN" unsafe isDoubleNaN :: Double -> Int
+foreign import ccall "isDoubleInfinite" unsafe isDoubleInfinite :: Double -> Int
+foreign import ccall "isDoubleDenormalized" unsafe isDoubleDenormalized :: Double -> Int
+foreign import ccall "isDoubleNegativeZero" unsafe isDoubleNegativeZero :: Double -> Int
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Coercion rules}
+%* *
+%*********************************************************
+
+\begin{code}
+{-# RULES
+"fromIntegral/Int->Float" fromIntegral = int2Float
+"fromIntegral/Int->Double" fromIntegral = int2Double
+"realToFrac/Float->Float" realToFrac = id :: Float -> Float
+"realToFrac/Float->Double" realToFrac = float2Double
+"realToFrac/Double->Float" realToFrac = double2Float
+"realToFrac/Double->Double" realToFrac = id :: Double -> Double
+ #-}
+\end{code}
diff --git a/libraries/base/GHC/Handle.hsc b/libraries/base/GHC/Handle.hsc
new file mode 100644
index 0000000000..c613d43af2
--- /dev/null
+++ b/libraries/base/GHC/Handle.hsc
@@ -0,0 +1,1191 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#undef DEBUG_DUMP
+#undef DEBUG
+
+-- -----------------------------------------------------------------------------
+-- $Id: Handle.hsc,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- (c) The University of Glasgow, 1994-2001
+--
+-- This module defines the basic operations on I/O "handles".
+
+module GHC.Handle (
+ withHandle, withHandle', withHandle_,
+ wantWritableHandle, wantReadableHandle, wantSeekableHandle,
+
+ newEmptyBuffer, allocateBuffer, readCharFromBuffer, writeCharIntoBuffer,
+ flushWriteBufferOnly, flushWriteBuffer, flushReadBuffer, fillReadBuffer,
+ read_off,
+
+ ioe_closedHandle, ioe_EOF, ioe_notReadable, ioe_notWritable,
+
+ stdin, stdout, stderr,
+ IOMode(..), IOModeEx(..), openFile, openFileEx, openFd,
+ hClose, hFileSize, hIsEOF, isEOF, hLookAhead, hSetBuffering, hSetBinaryMode,
+ hFlush,
+
+ HandlePosn(..), hGetPosn, hSetPosn,
+ SeekMode(..), hSeek,
+
+ hIsOpen, hIsClosed, hIsReadable, hIsWritable, hGetBuffering, hIsSeekable,
+ hSetEcho, hGetEcho, hIsTerminalDevice,
+ ioeGetFileName, ioeGetErrorString, ioeGetHandle,
+
+#ifdef DEBUG_DUMP
+ puts,
+#endif
+
+ ) where
+
+#include "HsCore.h"
+
+import Control.Monad
+import Data.Bits
+import Data.Maybe
+import Foreign
+import Foreign.C
+
+import GHC.Posix
+import GHC.Real
+
+import GHC.Arr
+import GHC.Base
+import GHC.Read ( Read )
+import GHC.List
+import GHC.IOBase
+import GHC.Exception
+import GHC.Enum
+import GHC.Num ( Integer(..), Num(..) )
+import GHC.Show
+import GHC.Real ( toInteger )
+
+import GHC.Conc
+
+-- -----------------------------------------------------------------------------
+-- TODO:
+
+-- hWaitForInput blocks (should use a timeout)
+
+-- unbuffered hGetLine is a bit dodgy
+
+-- hSetBuffering: can't change buffering on a stream,
+-- when the read buffer is non-empty? (no way to flush the buffer)
+
+-- ---------------------------------------------------------------------------
+-- Are files opened by default in text or binary mode, if the user doesn't
+-- specify?
+dEFAULT_OPEN_IN_BINARY_MODE :: Bool
+dEFAULT_OPEN_IN_BINARY_MODE = False
+
+-- ---------------------------------------------------------------------------
+-- Creating a new handle
+
+newFileHandle :: (MVar Handle__ -> IO ()) -> Handle__ -> IO Handle
+newFileHandle finalizer hc = do
+ m <- newMVar hc
+ addMVarFinalizer m (finalizer m)
+ return (FileHandle m)
+
+-- ---------------------------------------------------------------------------
+-- Working with Handles
+
+{-
+In the concurrent world, handles are locked during use. This is done
+by wrapping an MVar around the handle which acts as a mutex over
+operations on the handle.
+
+To avoid races, we use the following bracketing operations. The idea
+is to obtain the lock, do some operation and replace the lock again,
+whether the operation succeeded or failed. We also want to handle the
+case where the thread receives an exception while processing the IO
+operation: in these cases we also want to relinquish the lock.
+
+There are three versions of @withHandle@: corresponding to the three
+possible combinations of:
+
+ - the operation may side-effect the handle
+ - the operation may return a result
+
+If the operation generates an error or an exception is raised, the
+original handle is always replaced [ this is the case at the moment,
+but we might want to revisit this in the future --SDM ].
+-}
+
+{-# INLINE withHandle #-}
+withHandle :: String -> Handle -> (Handle__ -> IO (Handle__,a)) -> IO a
+withHandle fun h@(FileHandle m) act = withHandle' fun h m act
+withHandle fun h@(DuplexHandle r w) act = do
+ withHandle' fun h r act
+ withHandle' fun h w act
+
+withHandle' fun h m act =
+ block $ do
+ h_ <- takeMVar m
+ checkBufferInvariants h_
+ (h',v) <- catchException (act h_)
+ (\ ex -> putMVar m h_ >> throw (augmentIOError ex fun h h_))
+ checkBufferInvariants h'
+ putMVar m h'
+ return v
+
+{-# INLINE withHandle_ #-}
+withHandle_ :: String -> Handle -> (Handle__ -> IO a) -> IO a
+withHandle_ fun h@(FileHandle m) act = withHandle_' fun h m act
+withHandle_ fun h@(DuplexHandle m _) act = withHandle_' fun h m act
+
+withHandle_' fun h m act =
+ block $ do
+ h_ <- takeMVar m
+ checkBufferInvariants h_
+ v <- catchException (act h_)
+ (\ ex -> putMVar m h_ >> throw (augmentIOError ex fun h h_))
+ checkBufferInvariants h_
+ putMVar m h_
+ return v
+
+withAllHandles__ :: String -> Handle -> (Handle__ -> IO Handle__) -> IO ()
+withAllHandles__ fun h@(FileHandle m) act = withHandle__' fun h m act
+withAllHandles__ fun h@(DuplexHandle r w) act = do
+ withHandle__' fun h r act
+ withHandle__' fun h w act
+
+withHandle__' fun h m act =
+ block $ do
+ h_ <- takeMVar m
+ checkBufferInvariants h_
+ h' <- catchException (act h_)
+ (\ ex -> putMVar m h_ >> throw (augmentIOError ex fun h h_))
+ checkBufferInvariants h'
+ putMVar m h'
+ return ()
+
+augmentIOError (IOException (IOError _ iot _ str fp)) fun h h_
+ = IOException (IOError (Just h) iot fun str filepath)
+ where filepath | Just _ <- fp = fp
+ | otherwise = Just (haFilePath h_)
+augmentIOError other_exception _ _ _
+ = other_exception
+
+-- ---------------------------------------------------------------------------
+-- Wrapper for write operations.
+
+wantWritableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
+wantWritableHandle fun h@(FileHandle m) act
+ = wantWritableHandle' fun h m act
+wantWritableHandle fun h@(DuplexHandle _ m) act
+ = wantWritableHandle' fun h m act
+ -- ToDo: in the Duplex case, we don't need to checkWritableHandle
+
+wantWritableHandle'
+ :: String -> Handle -> MVar Handle__
+ -> (Handle__ -> IO a) -> IO a
+wantWritableHandle' fun h m act
+ = withHandle_' fun h m (checkWritableHandle act)
+
+checkWritableHandle act handle_
+ = case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ ReadHandle -> ioe_notWritable
+ ReadWriteHandle -> do
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+ new_buf <-
+ if not (bufferIsWritable buf)
+ then do b <- flushReadBuffer (haFD handle_) buf
+ return b{ bufState=WriteBuffer }
+ else return buf
+ writeIORef ref new_buf
+ act handle_
+ _other -> act handle_
+
+-- ---------------------------------------------------------------------------
+-- Wrapper for read operations.
+
+wantReadableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
+wantReadableHandle fun h@(FileHandle m) act
+ = wantReadableHandle' fun h m act
+wantReadableHandle fun h@(DuplexHandle m _) act
+ = wantReadableHandle' fun h m act
+ -- ToDo: in the Duplex case, we don't need to checkReadableHandle
+
+wantReadableHandle'
+ :: String -> Handle -> MVar Handle__
+ -> (Handle__ -> IO a) -> IO a
+wantReadableHandle' fun h m act
+ = withHandle_' fun h m (checkReadableHandle act)
+
+checkReadableHandle act handle_ =
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ AppendHandle -> ioe_notReadable
+ WriteHandle -> ioe_notReadable
+ ReadWriteHandle -> do
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+ when (bufferIsWritable buf) $ do
+ new_buf <- flushWriteBuffer (haFD handle_) buf
+ writeIORef ref new_buf{ bufState=ReadBuffer }
+ act handle_
+ _other -> act handle_
+
+-- ---------------------------------------------------------------------------
+-- Wrapper for seek operations.
+
+wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
+wantSeekableHandle fun h@(DuplexHandle _ _) _act =
+ ioException (IOError (Just h) IllegalOperation fun
+ "handle is not seekable" Nothing)
+wantSeekableHandle fun h@(FileHandle m) act =
+ withHandle_' fun h m (checkSeekableHandle act)
+
+checkSeekableHandle act handle_ =
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ AppendHandle -> ioe_notSeekable
+ _ | haIsBin handle_ -> act handle_
+ | otherwise -> ioe_notSeekable_notBin
+
+-- -----------------------------------------------------------------------------
+-- Handy IOErrors
+
+ioe_closedHandle, ioe_EOF,
+ ioe_notReadable, ioe_notWritable,
+ ioe_notSeekable, ioe_notSeekable_notBin :: IO a
+
+ioe_closedHandle = ioException
+ (IOError Nothing IllegalOperation ""
+ "handle is closed" Nothing)
+ioe_EOF = ioException
+ (IOError Nothing EOF "" "" Nothing)
+ioe_notReadable = ioException
+ (IOError Nothing IllegalOperation ""
+ "handle is not open for reading" Nothing)
+ioe_notWritable = ioException
+ (IOError Nothing IllegalOperation ""
+ "handle is not open for writing" Nothing)
+ioe_notSeekable = ioException
+ (IOError Nothing IllegalOperation ""
+ "handle is not seekable" Nothing)
+ioe_notSeekable_notBin = ioException
+ (IOError Nothing IllegalOperation ""
+ "seek operations are only allowed on binary-mode handles" Nothing)
+
+ioe_bufsiz :: Int -> IO a
+ioe_bufsiz n = ioException
+ (IOError Nothing InvalidArgument "hSetBuffering"
+ ("illegal buffer size " ++ showsPrec 9 n []) Nothing)
+ -- 9 => should be parens'ified.
+
+-- -----------------------------------------------------------------------------
+-- Handle Finalizers
+
+-- For a duplex handle, we arrange that the read side points to the write side
+-- (and hence keeps it alive if the read side is alive). This is done by
+-- having the haType field of the read side be ReadSideHandle with a pointer
+-- to the write side. The finalizer is then placed on the write side, and
+-- the handle only gets finalized once, when both sides are no longer
+-- required.
+
+stdHandleFinalizer :: MVar Handle__ -> IO ()
+stdHandleFinalizer m = do
+ h_ <- takeMVar m
+ flushWriteBufferOnly h_
+
+handleFinalizer :: MVar Handle__ -> IO ()
+handleFinalizer m = do
+ h_ <- takeMVar m
+ flushWriteBufferOnly h_
+ let fd = fromIntegral (haFD h_)
+ unlockFile fd
+ -- ToDo: closesocket() for a WINSOCK socket?
+ when (fd /= -1) (c_close fd >> return ())
+ return ()
+
+-- ---------------------------------------------------------------------------
+-- Grimy buffer operations
+
+#ifdef DEBUG
+checkBufferInvariants h_ = do
+ let ref = haBuffer h_
+ Buffer{ bufWPtr=w, bufRPtr=r, bufSize=size, bufState=state } <- readIORef ref
+ if not (
+ size > 0
+ && r <= w
+ && w <= size
+ && ( r /= w || (r == 0 && w == 0) )
+ && ( state /= WriteBuffer || r == 0 )
+ && ( state /= WriteBuffer || w < size ) -- write buffer is never full
+ )
+ then error "buffer invariant violation"
+ else return ()
+#else
+checkBufferInvariants h_ = return ()
+#endif
+
+newEmptyBuffer :: RawBuffer -> BufferState -> Int -> Buffer
+newEmptyBuffer b state size
+ = Buffer{ bufBuf=b, bufRPtr=0, bufWPtr=0, bufSize=size, bufState=state }
+
+allocateBuffer :: Int -> BufferState -> IO Buffer
+allocateBuffer sz@(I## size) state = IO $ \s ->
+ case newByteArray## size s of { (## s, b ##) ->
+ (## s, newEmptyBuffer b state sz ##) }
+
+writeCharIntoBuffer :: RawBuffer -> Int -> Char -> IO Int
+writeCharIntoBuffer slab (I## off) (C## c)
+ = IO $ \s -> case writeCharArray## slab off c s of
+ s -> (## s, I## (off +## 1##) ##)
+
+readCharFromBuffer :: RawBuffer -> Int -> IO (Char, Int)
+readCharFromBuffer slab (I## off)
+ = IO $ \s -> case readCharArray## slab off s of
+ (## s, c ##) -> (## s, (C## c, I## (off +## 1##)) ##)
+
+dEFAULT_BUFFER_SIZE = (#const BUFSIZ) :: Int
+
+getBuffer :: FD -> BufferState -> IO (IORef Buffer, BufferMode)
+getBuffer fd state = do
+ buffer <- allocateBuffer dEFAULT_BUFFER_SIZE state
+ ioref <- newIORef buffer
+ is_tty <- fdIsTTY fd
+
+ let buffer_mode
+ | is_tty = LineBuffering
+ | otherwise = BlockBuffering Nothing
+
+ return (ioref, buffer_mode)
+
+mkUnBuffer :: IO (IORef Buffer)
+mkUnBuffer = do
+ buffer <- allocateBuffer 1 ReadBuffer
+ newIORef buffer
+
+-- flushWriteBufferOnly flushes the buffer iff it contains pending write data.
+flushWriteBufferOnly :: Handle__ -> IO ()
+flushWriteBufferOnly h_ = do
+ let fd = haFD h_
+ ref = haBuffer h_
+ buf <- readIORef ref
+ new_buf <- if bufferIsWritable buf
+ then flushWriteBuffer fd buf
+ else return buf
+ writeIORef ref new_buf
+
+-- flushBuffer syncs the file with the buffer, including moving the
+-- file pointer backwards in the case of a read buffer.
+flushBuffer :: Handle__ -> IO ()
+flushBuffer h_ = do
+ let ref = haBuffer h_
+ buf <- readIORef ref
+
+ flushed_buf <-
+ case bufState buf of
+ ReadBuffer -> flushReadBuffer (haFD h_) buf
+ WriteBuffer -> flushWriteBuffer (haFD h_) buf
+
+ writeIORef ref flushed_buf
+
+-- When flushing a read buffer, we seek backwards by the number of
+-- characters in the buffer. The file descriptor must therefore be
+-- seekable: attempting to flush the read buffer on an unseekable
+-- handle is not allowed.
+
+flushReadBuffer :: FD -> Buffer -> IO Buffer
+flushReadBuffer fd buf
+ | bufferEmpty buf = return buf
+ | otherwise = do
+ let off = negate (bufWPtr buf - bufRPtr buf)
+# ifdef DEBUG_DUMP
+ puts ("flushReadBuffer: new file offset = " ++ show off ++ "\n")
+# endif
+ throwErrnoIfMinus1Retry "flushReadBuffer"
+ (c_lseek (fromIntegral fd) (fromIntegral off) (#const SEEK_CUR))
+ return buf{ bufWPtr=0, bufRPtr=0 }
+
+flushWriteBuffer :: FD -> Buffer -> IO Buffer
+flushWriteBuffer fd buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w } = do
+ let bytes = w - r
+#ifdef DEBUG_DUMP
+ puts ("flushWriteBuffer, fd=" ++ show fd ++ ", bytes=" ++ show bytes ++ "\n")
+#endif
+ if bytes == 0
+ then return (buf{ bufRPtr=0, bufWPtr=0 })
+ else do
+ res <- throwErrnoIfMinus1RetryMayBlock "flushWriteBuffer"
+ (write_off (fromIntegral fd) b (fromIntegral r)
+ (fromIntegral bytes))
+ (threadWaitWrite fd)
+ let res' = fromIntegral res
+ if res' < bytes
+ then flushWriteBuffer fd (buf{ bufRPtr = r + res' })
+ else return buf{ bufRPtr=0, bufWPtr=0 }
+
+foreign import "write_wrap" unsafe
+ write_off :: CInt -> RawBuffer -> Int -> CInt -> IO CInt
+#def inline \
+int write_wrap(int fd, void *ptr, HsInt off, int size) \
+{ return write(fd, ptr + off, size); }
+
+
+fillReadBuffer :: FD -> Bool -> Buffer -> IO Buffer
+fillReadBuffer fd is_line
+ buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w, bufSize=size } =
+ -- buffer better be empty:
+ assert (r == 0 && w == 0) $ do
+ fillReadBufferLoop fd is_line buf b w size
+
+-- For a line buffer, we just get the first chunk of data to arrive,
+-- and don't wait for the whole buffer to be full (but we *do* wait
+-- until some data arrives). This isn't really line buffering, but it
+-- appears to be what GHC has done for a long time, and I suspect it
+-- is more useful than line buffering in most cases.
+
+fillReadBufferLoop fd is_line buf b w size = do
+ let bytes = size - w
+ if bytes == 0 -- buffer full?
+ then return buf{ bufRPtr=0, bufWPtr=w }
+ else do
+#ifdef DEBUG_DUMP
+ puts ("fillReadBufferLoop: bytes = " ++ show bytes ++ "\n")
+#endif
+ res <- throwErrnoIfMinus1RetryMayBlock "fillReadBuffer"
+ (read_off fd b (fromIntegral w) (fromIntegral bytes))
+ (threadWaitRead fd)
+ let res' = fromIntegral res
+#ifdef DEBUG_DUMP
+ puts ("fillReadBufferLoop: res' = " ++ show res' ++ "\n")
+#endif
+ if res' == 0
+ then if w == 0
+ then ioe_EOF
+ else return buf{ bufRPtr=0, bufWPtr=w }
+ else if res' < bytes && not is_line
+ then fillReadBufferLoop fd is_line buf b (w+res') size
+ else return buf{ bufRPtr=0, bufWPtr=w+res' }
+
+foreign import "read_wrap" unsafe
+ read_off :: FD -> RawBuffer -> Int -> CInt -> IO CInt
+#def inline \
+int read_wrap(int fd, void *ptr, HsInt off, int size) \
+{ return read(fd, ptr + off, size); }
+
+-- ---------------------------------------------------------------------------
+-- Standard Handles
+
+-- Three handles are allocated during program initialisation. The first
+-- two manage input or output from the Haskell program's standard input
+-- or output channel respectively. The third manages output to the
+-- standard error channel. These handles are initially open.
+
+fd_stdin = 0 :: FD
+fd_stdout = 1 :: FD
+fd_stderr = 2 :: FD
+
+stdin :: Handle
+stdin = unsafePerformIO $ do
+ -- ToDo: acquire lock
+ setNonBlockingFD fd_stdin
+ (buf, bmode) <- getBuffer fd_stdin ReadBuffer
+ spares <- newIORef BufferListNil
+ newFileHandle stdHandleFinalizer
+ (Handle__ { haFD = fd_stdin,
+ haType = ReadHandle,
+ haIsBin = dEFAULT_OPEN_IN_BINARY_MODE,
+ haBufferMode = bmode,
+ haFilePath = "<stdin>",
+ haBuffer = buf,
+ haBuffers = spares
+ })
+
+stdout :: Handle
+stdout = unsafePerformIO $ do
+ -- ToDo: acquire lock
+ -- We don't set non-blocking mode on stdout or sterr, because
+ -- some shells don't recover properly.
+ -- setNonBlockingFD fd_stdout
+ (buf, bmode) <- getBuffer fd_stdout WriteBuffer
+ spares <- newIORef BufferListNil
+ newFileHandle stdHandleFinalizer
+ (Handle__ { haFD = fd_stdout,
+ haType = WriteHandle,
+ haIsBin = dEFAULT_OPEN_IN_BINARY_MODE,
+ haBufferMode = bmode,
+ haFilePath = "<stdout>",
+ haBuffer = buf,
+ haBuffers = spares
+ })
+
+stderr :: Handle
+stderr = unsafePerformIO $ do
+ -- ToDo: acquire lock
+ -- We don't set non-blocking mode on stdout or sterr, because
+ -- some shells don't recover properly.
+ -- setNonBlockingFD fd_stderr
+ buffer <- mkUnBuffer
+ spares <- newIORef BufferListNil
+ newFileHandle stdHandleFinalizer
+ (Handle__ { haFD = fd_stderr,
+ haType = WriteHandle,
+ haIsBin = dEFAULT_OPEN_IN_BINARY_MODE,
+ haBufferMode = NoBuffering,
+ haFilePath = "<stderr>",
+ haBuffer = buffer,
+ haBuffers = spares
+ })
+
+-- ---------------------------------------------------------------------------
+-- Opening and Closing Files
+
+{-
+Computation `openFile file mode' allocates and returns a new, open
+handle to manage the file `file'. It manages input if `mode'
+is `ReadMode', output if `mode' is `WriteMode' or `AppendMode',
+and both input and output if mode is `ReadWriteMode'.
+
+If the file does not exist and it is opened for output, it should be
+created as a new file. If `mode' is `WriteMode' and the file
+already exists, then it should be truncated to zero length. The
+handle is positioned at the end of the file if `mode' is
+`AppendMode', and otherwise at the beginning (in which case its
+internal position is 0).
+
+Implementations should enforce, locally to the Haskell process,
+multiple-reader single-writer locking on files, which is to say that
+there may either be many handles on the same file which manage input,
+or just one handle on the file which manages output. If any open or
+semi-closed handle is managing a file for output, no new handle can be
+allocated for that file. If any open or semi-closed handle is
+managing a file for input, new handles can only be allocated if they
+do not manage output.
+
+Two files are the same if they have the same absolute name. An
+implementation is free to impose stricter conditions.
+-}
+
+data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
+ deriving (Eq, Ord, Ix, Enum, Read, Show)
+
+data IOModeEx
+ = BinaryMode IOMode
+ | TextMode IOMode
+ deriving (Eq, Read, Show)
+
+addFilePathToIOError fun fp (IOException (IOError h iot _ str _))
+ = IOException (IOError h iot fun str (Just fp))
+addFilePathToIOError _ _ other_exception
+ = other_exception
+
+openFile :: FilePath -> IOMode -> IO Handle
+openFile fp im =
+ catch
+ (openFile' fp (if dEFAULT_OPEN_IN_BINARY_MODE
+ then BinaryMode im
+ else TextMode im))
+ (\e -> throw (addFilePathToIOError "openFile" fp e))
+
+openFileEx :: FilePath -> IOModeEx -> IO Handle
+openFileEx fp m =
+ catch
+ (openFile' fp m)
+ (\e -> throw (addFilePathToIOError "openFileEx" fp e))
+
+
+openFile' filepath ex_mode =
+ withCString filepath $ \ f ->
+
+ let
+ (mode, binary) =
+ case ex_mode of
+ BinaryMode bmo -> (bmo, True)
+ TextMode tmo -> (tmo, False)
+
+ oflags1 = case mode of
+ ReadMode -> read_flags
+ WriteMode -> write_flags
+ ReadWriteMode -> rw_flags
+ AppendMode -> append_flags
+
+ binary_flags
+#ifdef HAVE_O_BINARY
+ | binary = o_BINARY
+#endif
+ | otherwise = 0
+
+ oflags = oflags1 .|. binary_flags
+ in do
+
+ -- the old implementation had a complicated series of three opens,
+ -- which is perhaps because we have to be careful not to open
+ -- directories. However, the man pages I've read say that open()
+ -- always returns EISDIR if the file is a directory and was opened
+ -- for writing, so I think we're ok with a single open() here...
+ fd <- fromIntegral `liftM`
+ throwErrnoIfMinus1Retry "openFile"
+ (c_open f (fromIntegral oflags) 0o666)
+
+ openFd fd filepath mode binary
+
+
+std_flags = o_NONBLOCK .|. o_NOCTTY
+output_flags = std_flags .|. o_CREAT
+read_flags = std_flags .|. o_RDONLY
+write_flags = output_flags .|. o_WRONLY .|. o_TRUNC
+rw_flags = output_flags .|. o_RDWR
+append_flags = output_flags .|. o_WRONLY .|. o_APPEND
+
+-- ---------------------------------------------------------------------------
+-- openFd
+
+openFd :: FD -> FilePath -> IOMode -> Bool -> IO Handle
+openFd fd filepath mode binary = do
+ -- turn on non-blocking mode
+ setNonBlockingFD fd
+
+ let (ha_type, write) =
+ case mode of
+ ReadMode -> ( ReadHandle, False )
+ WriteMode -> ( WriteHandle, True )
+ ReadWriteMode -> ( ReadWriteHandle, True )
+ AppendMode -> ( AppendHandle, True )
+
+ -- open() won't tell us if it was a directory if we only opened for
+ -- reading, so check again.
+ fd_type <- fdType fd
+ case fd_type of
+ Directory ->
+ ioException (IOError Nothing InappropriateType "openFile"
+ "is a directory" Nothing)
+
+ Stream
+ | ReadWriteHandle <- ha_type -> mkDuplexHandle fd filepath binary
+ | otherwise -> mkFileHandle fd filepath ha_type binary
+
+ -- regular files need to be locked
+ RegularFile -> do
+ r <- lockFile (fromIntegral fd) (fromBool write) 1{-exclusive-}
+ when (r == -1) $
+ ioException (IOError Nothing ResourceBusy "openFile"
+ "file is locked" Nothing)
+ mkFileHandle fd filepath ha_type binary
+
+
+foreign import "lockFile" unsafe
+ lockFile :: CInt -> CInt -> CInt -> IO CInt
+
+foreign import "unlockFile" unsafe
+ unlockFile :: CInt -> IO CInt
+
+mkFileHandle :: FD -> FilePath -> HandleType -> Bool -> IO Handle
+mkFileHandle fd filepath ha_type binary = do
+ (buf, bmode) <- getBuffer fd (initBufferState ha_type)
+ spares <- newIORef BufferListNil
+ newFileHandle handleFinalizer
+ (Handle__ { haFD = fd,
+ haType = ha_type,
+ haIsBin = binary,
+ haBufferMode = bmode,
+ haFilePath = filepath,
+ haBuffer = buf,
+ haBuffers = spares
+ })
+
+mkDuplexHandle :: FD -> FilePath -> Bool -> IO Handle
+mkDuplexHandle fd filepath binary = do
+ (w_buf, w_bmode) <- getBuffer fd WriteBuffer
+ w_spares <- newIORef BufferListNil
+ let w_handle_ =
+ Handle__ { haFD = fd,
+ haType = WriteHandle,
+ haIsBin = binary,
+ haBufferMode = w_bmode,
+ haFilePath = filepath,
+ haBuffer = w_buf,
+ haBuffers = w_spares
+ }
+ write_side <- newMVar w_handle_
+
+ (r_buf, r_bmode) <- getBuffer fd ReadBuffer
+ r_spares <- newIORef BufferListNil
+ let r_handle_ =
+ Handle__ { haFD = fd,
+ haType = ReadSideHandle write_side,
+ haIsBin = binary,
+ haBufferMode = r_bmode,
+ haFilePath = filepath,
+ haBuffer = r_buf,
+ haBuffers = r_spares
+ }
+ read_side <- newMVar r_handle_
+
+ addMVarFinalizer write_side (handleFinalizer write_side)
+ return (DuplexHandle read_side write_side)
+
+
+initBufferState ReadHandle = ReadBuffer
+initBufferState _ = WriteBuffer
+
+-- ---------------------------------------------------------------------------
+-- Closing a handle
+
+-- Computation `hClose hdl' makes handle `hdl' closed. Before the
+-- computation finishes, any items buffered for output and not already
+-- sent to the operating system are flushed as for `hFlush'.
+
+-- For a duplex handle, we close&flush the write side, and just close
+-- the read side.
+
+hClose :: Handle -> IO ()
+hClose h@(FileHandle m) = hClose' h m
+hClose h@(DuplexHandle r w) = do
+ hClose' h w
+ withHandle__' "hClose" h r $ \ handle_ -> do
+ return handle_{ haFD = -1,
+ haType = ClosedHandle
+ }
+
+hClose' h m =
+ withHandle__' "hClose" h m $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> return handle_
+ _ -> do
+ let fd = fromIntegral (haFD handle_)
+ flushWriteBufferOnly handle_
+ throwErrnoIfMinus1Retry_ "hClose" (c_close fd)
+
+ -- free the spare buffers
+ writeIORef (haBuffers handle_) BufferListNil
+
+ -- unlock it
+ unlockFile fd
+
+ -- we must set the fd to -1, because the finalizer is going
+ -- to run eventually and try to close/unlock it.
+ return (handle_{ haFD = -1,
+ haType = ClosedHandle
+ })
+
+-----------------------------------------------------------------------------
+-- Detecting the size of a file
+
+-- For a handle `hdl' which attached to a physical file, `hFileSize
+-- hdl' returns the size of `hdl' in terms of the number of items
+-- which can be read from `hdl'.
+
+hFileSize :: Handle -> IO Integer
+hFileSize handle =
+ withHandle_ "hFileSize" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ _ -> do flushWriteBufferOnly handle_
+ r <- fdFileSize (haFD handle_)
+ if r /= -1
+ then return r
+ else ioException (IOError Nothing InappropriateType "hFileSize"
+ "not a regular file" Nothing)
+
+-- ---------------------------------------------------------------------------
+-- Detecting the End of Input
+
+-- For a readable handle `hdl', `hIsEOF hdl' returns
+-- `True' if no further input can be taken from `hdl' or for a
+-- physical file, if the current I/O position is equal to the length of
+-- the file. Otherwise, it returns `False'.
+
+hIsEOF :: Handle -> IO Bool
+hIsEOF handle =
+ catch
+ (do hLookAhead handle; return False)
+ (\e -> if isEOFError e then return True else throw e)
+
+isEOF :: IO Bool
+isEOF = hIsEOF stdin
+
+-- ---------------------------------------------------------------------------
+-- Looking ahead
+
+-- hLookahead returns the next character from the handle without
+-- removing it from the input buffer, blocking until a character is
+-- available.
+
+hLookAhead :: Handle -> IO Char
+hLookAhead handle = do
+ wantReadableHandle "hLookAhead" handle $ \handle_ -> do
+ let ref = haBuffer handle_
+ fd = haFD handle_
+ is_line = haBufferMode handle_ == LineBuffering
+ buf <- readIORef ref
+
+ -- fill up the read buffer if necessary
+ new_buf <- if bufferEmpty buf
+ then fillReadBuffer fd is_line buf
+ else return buf
+
+ writeIORef ref new_buf
+
+ (c,_) <- readCharFromBuffer (bufBuf buf) (bufRPtr buf)
+ return c
+
+-- ---------------------------------------------------------------------------
+-- Buffering Operations
+
+-- Three kinds of buffering are supported: line-buffering,
+-- block-buffering or no-buffering. See GHC.IOBase for definition and
+-- further explanation of what the type represent.
+
+-- Computation `hSetBuffering hdl mode' sets the mode of buffering for
+-- handle hdl on subsequent reads and writes.
+--
+-- * If mode is LineBuffering, line-buffering should be enabled if possible.
+--
+-- * If mode is `BlockBuffering size', then block-buffering
+-- should be enabled if possible. The size of the buffer is n items
+-- if size is `Just n' and is otherwise implementation-dependent.
+--
+-- * If mode is NoBuffering, then buffering is disabled if possible.
+
+-- If the buffer mode is changed from BlockBuffering or
+-- LineBuffering to NoBuffering, then any items in the output
+-- buffer are written to the device, and any items in the input buffer
+-- are discarded. The default buffering mode when a handle is opened
+-- is implementation-dependent and may depend on the object which is
+-- attached to that handle.
+
+hSetBuffering :: Handle -> BufferMode -> IO ()
+hSetBuffering handle mode =
+ withAllHandles__ "hSetBuffering" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ _ -> do
+ {- Note:
+ - we flush the old buffer regardless of whether
+ the new buffer could fit the contents of the old buffer
+ or not.
+ - allow a handle's buffering to change even if IO has
+ occurred (ANSI C spec. does not allow this, nor did
+ the previous implementation of IO.hSetBuffering).
+ - a non-standard extension is to allow the buffering
+ of semi-closed handles to change [sof 6/98]
+ -}
+ flushBuffer handle_
+
+ let state = initBufferState (haType handle_)
+ new_buf <-
+ case mode of
+ -- we always have a 1-character read buffer for
+ -- unbuffered handles: it's needed to
+ -- support hLookAhead.
+ NoBuffering -> allocateBuffer 1 ReadBuffer
+ LineBuffering -> allocateBuffer dEFAULT_BUFFER_SIZE state
+ BlockBuffering Nothing -> allocateBuffer dEFAULT_BUFFER_SIZE state
+ BlockBuffering (Just n) | n <= 0 -> ioe_bufsiz n
+ | otherwise -> allocateBuffer n state
+ writeIORef (haBuffer handle_) new_buf
+
+ -- for input terminals we need to put the terminal into
+ -- cooked or raw mode depending on the type of buffering.
+ is_tty <- fdIsTTY (haFD handle_)
+ when (is_tty && isReadableHandleType (haType handle_)) $
+ case mode of
+ NoBuffering -> setCooked (haFD handle_) False
+ _ -> setCooked (haFD handle_) True
+
+ -- throw away spare buffers, they might be the wrong size
+ writeIORef (haBuffers handle_) BufferListNil
+
+ return (handle_{ haBufferMode = mode })
+
+-- -----------------------------------------------------------------------------
+-- hFlush
+
+-- The action `hFlush hdl' causes any items buffered for output
+-- in handle `hdl' to be sent immediately to the operating
+-- system.
+
+hFlush :: Handle -> IO ()
+hFlush handle =
+ wantWritableHandle "hFlush" handle $ \ handle_ -> do
+ buf <- readIORef (haBuffer handle_)
+ if bufferIsWritable buf && not (bufferEmpty buf)
+ then do flushed_buf <- flushWriteBuffer (haFD handle_) buf
+ writeIORef (haBuffer handle_) flushed_buf
+ else return ()
+
+
+-- -----------------------------------------------------------------------------
+-- Repositioning Handles
+
+data HandlePosn = HandlePosn Handle HandlePosition
+
+instance Eq HandlePosn where
+ (HandlePosn h1 p1) == (HandlePosn h2 p2) = p1==p2 && h1==h2
+
+ -- HandlePosition is the Haskell equivalent of POSIX' off_t.
+ -- We represent it as an Integer on the Haskell side, but
+ -- cheat slightly in that hGetPosn calls upon a C helper
+ -- that reports the position back via (merely) an Int.
+type HandlePosition = Integer
+
+-- Computation `hGetPosn hdl' returns the current I/O position of
+-- `hdl' as an abstract position. Computation `hSetPosn p' sets the
+-- position of `hdl' to a previously obtained position `p'.
+
+hGetPosn :: Handle -> IO HandlePosn
+hGetPosn handle =
+ wantSeekableHandle "hGetPosn" handle $ \ handle_ -> do
+
+#if defined(_WIN32)
+ -- urgh, on Windows we have to worry about \n -> \r\n translation,
+ -- so we can't easily calculate the file position using the
+ -- current buffer size. Just flush instead.
+ flushBuffer handle_
+#endif
+ let fd = fromIntegral (haFD handle_)
+ posn <- fromIntegral `liftM`
+ throwErrnoIfMinus1Retry "hGetPosn"
+ (c_lseek fd 0 (#const SEEK_CUR))
+
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+
+ let real_posn
+ | bufferIsWritable buf = posn + fromIntegral (bufWPtr buf)
+ | otherwise = posn - fromIntegral (bufWPtr buf - bufRPtr buf)
+# ifdef DEBUG_DUMP
+ puts ("\nhGetPosn: (fd, posn, real_posn) = " ++ show (fd, posn, real_posn) ++ "\n")
+ puts (" (bufWPtr, bufRPtr) = " ++ show (bufWPtr buf, bufRPtr buf) ++ "\n")
+# endif
+ return (HandlePosn handle real_posn)
+
+
+hSetPosn :: HandlePosn -> IO ()
+hSetPosn (HandlePosn h i) = hSeek h AbsoluteSeek i
+
+-- ---------------------------------------------------------------------------
+-- hSeek
+
+{-
+The action `hSeek hdl mode i' sets the position of handle
+`hdl' depending on `mode'. If `mode' is
+
+ * AbsoluteSeek - The position of `hdl' is set to `i'.
+ * RelativeSeek - The position of `hdl' is set to offset `i' from
+ the current position.
+ * SeekFromEnd - The position of `hdl' is set to offset `i' from
+ the end of the file.
+
+Some handles may not be seekable (see `hIsSeekable'), or only
+support a subset of the possible positioning operations (e.g. it may
+only be possible to seek to the end of a tape, or to a positive
+offset from the beginning or current position).
+
+It is not possible to set a negative I/O position, or for a physical
+file, an I/O position beyond the current end-of-file.
+
+Note:
+ - when seeking using `SeekFromEnd', positive offsets (>=0) means
+ seeking at or past EOF.
+
+ - we possibly deviate from the report on the issue of seeking within
+ the buffer and whether to flush it or not. The report isn't exactly
+ clear here.
+-}
+
+data SeekMode = AbsoluteSeek | RelativeSeek | SeekFromEnd
+ deriving (Eq, Ord, Ix, Enum, Read, Show)
+
+hSeek :: Handle -> SeekMode -> Integer -> IO ()
+hSeek handle mode offset =
+ wantSeekableHandle "hSeek" handle $ \ handle_ -> do
+# ifdef DEBUG_DUMP
+ puts ("hSeek " ++ show (mode,offset) ++ "\n")
+# endif
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+ let r = bufRPtr buf
+ w = bufWPtr buf
+ fd = haFD handle_
+
+ let do_seek =
+ throwErrnoIfMinus1Retry_ "hSeek"
+ (c_lseek (fromIntegral (haFD handle_)) (fromIntegral offset) whence)
+
+ whence :: CInt
+ whence = case mode of
+ AbsoluteSeek -> (#const SEEK_SET)
+ RelativeSeek -> (#const SEEK_CUR)
+ SeekFromEnd -> (#const SEEK_END)
+
+ if bufferIsWritable buf
+ then do new_buf <- flushWriteBuffer fd buf
+ writeIORef ref new_buf
+ do_seek
+ else do
+
+ if mode == RelativeSeek && offset >= 0 && offset < fromIntegral (w - r)
+ then writeIORef ref buf{ bufRPtr = r + fromIntegral offset }
+ else do
+
+ new_buf <- flushReadBuffer (haFD handle_) buf
+ writeIORef ref new_buf
+ do_seek
+
+-- -----------------------------------------------------------------------------
+-- Handle Properties
+
+-- A number of operations return information about the properties of a
+-- handle. Each of these operations returns `True' if the handle has
+-- the specified property, and `False' otherwise.
+
+hIsOpen :: Handle -> IO Bool
+hIsOpen handle =
+ withHandle_ "hIsOpen" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> return False
+ SemiClosedHandle -> return False
+ _ -> return True
+
+hIsClosed :: Handle -> IO Bool
+hIsClosed handle =
+ withHandle_ "hIsClosed" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> return True
+ _ -> return False
+
+{- not defined, nor exported, but mentioned
+ here for documentation purposes:
+
+ hSemiClosed :: Handle -> IO Bool
+ hSemiClosed h = do
+ ho <- hIsOpen h
+ hc <- hIsClosed h
+ return (not (ho || hc))
+-}
+
+hIsReadable :: Handle -> IO Bool
+hIsReadable (DuplexHandle _ _) = return True
+hIsReadable handle =
+ withHandle_ "hIsReadable" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ htype -> return (isReadableHandleType htype)
+
+hIsWritable :: Handle -> IO Bool
+hIsWritable (DuplexHandle _ _) = return False
+hIsWritable handle =
+ withHandle_ "hIsWritable" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ htype -> return (isWritableHandleType htype)
+
+-- Querying how a handle buffers its data:
+
+hGetBuffering :: Handle -> IO BufferMode
+hGetBuffering handle =
+ withHandle_ "hGetBuffering" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ _ ->
+ -- We're being non-standard here, and allow the buffering
+ -- of a semi-closed handle to be queried. -- sof 6/98
+ return (haBufferMode handle_) -- could be stricter..
+
+hIsSeekable :: Handle -> IO Bool
+hIsSeekable handle =
+ withHandle_ "hIsSeekable" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ AppendHandle -> return False
+ _ -> do t <- fdType (haFD handle_)
+ return (t == RegularFile && haIsBin handle_)
+
+-- -----------------------------------------------------------------------------
+-- Changing echo status
+
+-- Non-standard GHC extension is to allow the echoing status
+-- of a handles connected to terminals to be reconfigured:
+
+hSetEcho :: Handle -> Bool -> IO ()
+hSetEcho handle on = do
+ isT <- hIsTerminalDevice handle
+ if not isT
+ then return ()
+ else
+ withHandle_ "hSetEcho" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ _ -> setEcho (haFD handle_) on
+
+hGetEcho :: Handle -> IO Bool
+hGetEcho handle = do
+ isT <- hIsTerminalDevice handle
+ if not isT
+ then return False
+ else
+ withHandle_ "hGetEcho" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ _ -> getEcho (haFD handle_)
+
+hIsTerminalDevice :: Handle -> IO Bool
+hIsTerminalDevice handle = do
+ withHandle_ "hIsTerminalDevice" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ _ -> fdIsTTY (haFD handle_)
+
+-- -----------------------------------------------------------------------------
+-- hSetBinaryMode
+
+#ifdef _WIN32
+hSetBinaryMode handle bin =
+ withHandle "hSetBinaryMode" handle $ \ handle_ ->
+ do let flg | bin = (#const O_BINARY)
+ | otherwise = (#const O_TEXT)
+ throwErrnoIfMinus1_ "hSetBinaryMode"
+ (setmode (fromIntegral (haFD handle_)) flg)
+ return (handle_{haIsBin=bin}, ())
+
+foreign import "setmode" setmode :: CInt -> CInt -> IO CInt
+#else
+hSetBinaryMode handle bin =
+ withHandle "hSetBinaryMode" handle $ \ handle_ ->
+ return (handle_{haIsBin=bin}, ())
+#endif
+
+-- -----------------------------------------------------------------------------
+-- Miscellaneous
+
+-- These three functions are meant to get things out of an IOError.
+
+ioeGetFileName :: IOError -> Maybe FilePath
+ioeGetErrorString :: IOError -> String
+ioeGetHandle :: IOError -> Maybe Handle
+
+ioeGetHandle (IOException (IOError h _ _ _ _)) = h
+ioeGetHandle (UserError _) = Nothing
+ioeGetHandle _ = error "IO.ioeGetHandle: not an IO error"
+
+ioeGetErrorString (IOException (IOError _ iot _ _ _)) = show iot
+ioeGetErrorString (UserError str) = str
+ioeGetErrorString _ = error "IO.ioeGetErrorString: not an IO error"
+
+ioeGetFileName (IOException (IOError _ _ _ _ fn)) = fn
+ioeGetFileName (UserError _) = Nothing
+ioeGetFileName _ = error "IO.ioeGetFileName: not an IO error"
+
+-- ---------------------------------------------------------------------------
+-- debugging
+
+#ifdef DEBUG_DUMP
+puts :: String -> IO ()
+puts s = withCString s $ \cstr -> do c_write 1 cstr (fromIntegral (length s))
+ return ()
+#endif
diff --git a/libraries/base/GHC/IO.hsc b/libraries/base/GHC/IO.hsc
new file mode 100644
index 0000000000..49046f9785
--- /dev/null
+++ b/libraries/base/GHC/IO.hsc
@@ -0,0 +1,787 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#undef DEBUG_DUMP
+
+-- -----------------------------------------------------------------------------
+-- $Id: IO.hsc,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- (c) The University of Glasgow, 1992-2001
+--
+-- Module GHC.IO
+
+-- This module defines all basic IO operations.
+-- These are needed for the IO operations exported by Prelude,
+-- but as it happens they also do everything required by library
+-- module IO.
+
+module GHC.IO where
+
+#include "HsCore.h"
+#include "GHC/Handle_hsc.h"
+
+import Foreign
+import Foreign.C
+
+import Data.Maybe
+import Control.Monad
+
+import GHC.ByteArr
+import GHC.Enum
+import GHC.Base
+import GHC.Posix
+import GHC.IOBase
+import GHC.Handle -- much of the real stuff is in here
+import GHC.Real
+import GHC.Num
+import GHC.Show
+import GHC.List
+import GHC.Exception ( ioError, catch, throw )
+import GHC.Conc
+
+-- ---------------------------------------------------------------------------
+-- Simple input operations
+
+-- Computation "hReady hdl" indicates whether at least
+-- one item is available for input from handle "hdl".
+
+-- If hWaitForInput finds anything in the Handle's buffer, it
+-- immediately returns. If not, it tries to read from the underlying
+-- OS handle. Notice that for buffered Handles connected to terminals
+-- this means waiting until a complete line is available.
+
+hWaitForInput :: Handle -> Int -> IO Bool
+hWaitForInput h msecs = do
+ wantReadableHandle "hReady" h $ \ handle_ -> do
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+
+ if not (bufferEmpty buf)
+ then return True
+ else do
+
+ r <- throwErrnoIfMinus1Retry "hReady"
+ (inputReady (fromIntegral (haFD handle_)) (fromIntegral msecs))
+ return (r /= 0)
+
+foreign import "inputReady"
+ inputReady :: CInt -> CInt -> IO CInt
+
+-- ---------------------------------------------------------------------------
+-- hGetChar
+
+-- hGetChar reads the next character from a handle,
+-- blocking until a character is available.
+
+hGetChar :: Handle -> IO Char
+hGetChar handle =
+ wantReadableHandle "hGetChar" handle $ \handle_ -> do
+
+ let fd = haFD handle_
+ ref = haBuffer handle_
+
+ buf <- readIORef ref
+ if not (bufferEmpty buf)
+ then hGetcBuffered fd ref buf
+ else do
+
+ -- buffer is empty.
+ case haBufferMode handle_ of
+ LineBuffering -> do
+ new_buf <- fillReadBuffer fd True buf
+ hGetcBuffered fd ref new_buf
+ BlockBuffering _ -> do
+ new_buf <- fillReadBuffer fd False buf
+ hGetcBuffered fd ref new_buf
+ NoBuffering -> do
+ -- make use of the minimal buffer we already have
+ let raw = bufBuf buf
+ r <- throwErrnoIfMinus1RetryMayBlock "hGetChar"
+ (read_off (fromIntegral fd) raw 0 1)
+ (threadWaitRead fd)
+ if r == 0
+ then ioe_EOF
+ else do (c,_) <- readCharFromBuffer raw 0
+ return c
+
+hGetcBuffered fd ref buf@Buffer{ bufBuf=b, bufRPtr=r, bufWPtr=w }
+ = do (c,r) <- readCharFromBuffer b r
+ let new_buf | r == w = buf{ bufRPtr=0, bufWPtr=0 }
+ | otherwise = buf{ bufRPtr=r }
+ writeIORef ref new_buf
+ return c
+
+-- ---------------------------------------------------------------------------
+-- hGetLine
+
+-- If EOF is reached before EOL is encountered, ignore the EOF and
+-- return the partial line. Next attempt at calling hGetLine on the
+-- handle will yield an EOF IO exception though.
+
+-- ToDo: the unbuffered case is wrong: it doesn't lock the handle for
+-- the duration.
+hGetLine :: Handle -> IO String
+hGetLine h = do
+ m <- wantReadableHandle "hGetLine" h $ \ handle_ -> do
+ case haBufferMode handle_ of
+ NoBuffering -> return Nothing
+ LineBuffering -> do
+ l <- hGetLineBuffered handle_
+ return (Just l)
+ BlockBuffering _ -> do
+ l <- hGetLineBuffered handle_
+ return (Just l)
+ case m of
+ Nothing -> hGetLineUnBuffered h
+ Just l -> return l
+
+
+hGetLineBuffered handle_ = do
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+ hGetLineBufferedLoop handle_ ref buf []
+
+
+hGetLineBufferedLoop handle_ ref
+ buf@Buffer{ bufRPtr=r, bufWPtr=w, bufBuf=raw } xss =
+ let
+ -- find the end-of-line character, if there is one
+ loop raw r
+ | r == w = return (False, w)
+ | otherwise = do
+ (c,r') <- readCharFromBuffer raw r
+ if c == '\n'
+ then return (True, r) -- NB. not r': don't include the '\n'
+ else loop raw r'
+ in do
+ (eol, off) <- loop raw r
+
+#ifdef DEBUG_DUMP
+ puts ("hGetLineBufferedLoop: r=" ++ show r ++ ", w=" ++ show w ++ ", off=" ++ show off ++ "\n")
+#endif
+
+ xs <- unpack raw r off
+ if eol
+ then do if w == off + 1
+ then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ else writeIORef ref buf{ bufRPtr = off + 1 }
+ return (concat (reverse (xs:xss)))
+ else do
+ maybe_buf <- maybeFillReadBuffer (haFD handle_) True
+ buf{ bufWPtr=0, bufRPtr=0 }
+ case maybe_buf of
+ -- Nothing indicates we caught an EOF, and we may have a
+ -- partial line to return.
+ Nothing -> let str = concat (reverse (xs:xss)) in
+ if not (null str)
+ then return str
+ else ioe_EOF
+ Just new_buf ->
+ hGetLineBufferedLoop handle_ ref new_buf (xs:xss)
+
+
+unpack :: RawBuffer -> Int -> Int -> IO [Char]
+unpack buf r 0 = return ""
+unpack buf (I## r) (I## len) = IO $ \s -> unpack [] (len -## 1##) s
+ where
+ unpack acc i s
+ | i <## r = (## s, acc ##)
+ | otherwise =
+ case readCharArray## buf i s of
+ (## s, ch ##) -> unpack (C## ch : acc) (i -## 1##) s
+
+
+hGetLineUnBuffered :: Handle -> IO String
+hGetLineUnBuffered h = do
+ c <- hGetChar h
+ if c == '\n' then
+ return ""
+ else do
+ l <- getRest
+ return (c:l)
+ where
+ getRest = do
+ c <-
+ catch
+ (hGetChar h)
+ (\ err -> do
+ if isEOFError err then
+ return '\n'
+ else
+ ioError err)
+ if c == '\n' then
+ return ""
+ else do
+ s <- getRest
+ return (c:s)
+
+-- -----------------------------------------------------------------------------
+-- hGetContents
+
+-- hGetContents returns the list of characters corresponding to the
+-- unread portion of the channel or file managed by the handle, which
+-- is made semi-closed.
+
+-- hGetContents on a DuplexHandle only affects the read side: you can
+-- carry on writing to it afterwards.
+
+hGetContents :: Handle -> IO String
+hGetContents handle@(DuplexHandle r w)
+ = withHandle' "hGetContents" handle r (hGetContents' handle)
+hGetContents handle@(FileHandle m)
+ = withHandle' "hGetContents" handle m (hGetContents' handle)
+
+hGetContents' handle handle_ =
+ case haType handle_ of
+ ClosedHandle -> ioe_closedHandle
+ SemiClosedHandle -> ioe_closedHandle
+ AppendHandle -> ioe_notReadable
+ WriteHandle -> ioe_notReadable
+ _ -> do xs <- lazyRead handle
+ return (handle_{ haType=SemiClosedHandle}, xs )
+
+-- Note that someone may close the semi-closed handle (or change its
+-- buffering), so each time these lazy read functions are pulled on,
+-- they have to check whether the handle has indeed been closed.
+
+lazyRead :: Handle -> IO String
+lazyRead handle =
+ unsafeInterleaveIO $
+ withHandle_ "lazyRead" handle $ \ handle_ -> do
+ case haType handle_ of
+ ClosedHandle -> return ""
+ SemiClosedHandle -> lazyRead' handle handle_
+ _ -> ioException
+ (IOError (Just handle) IllegalOperation "lazyRead"
+ "illegal handle type" Nothing)
+
+lazyRead' h handle_ = do
+ let ref = haBuffer handle_
+ fd = haFD handle_
+
+ -- even a NoBuffering handle can have a char in the buffer...
+ -- (see hLookAhead)
+ buf <- readIORef ref
+ if not (bufferEmpty buf)
+ then lazyReadBuffered h fd ref buf
+ else do
+
+ case haBufferMode handle_ of
+ NoBuffering -> do
+ -- make use of the minimal buffer we already have
+ let raw = bufBuf buf
+ fd = haFD handle_
+ r <- throwErrnoIfMinus1RetryMayBlock "hGetChar"
+ (read_off (fromIntegral fd) raw 0 1)
+ (threadWaitRead fd)
+ if r == 0
+ then return ""
+ else do (c,_) <- readCharFromBuffer raw 0
+ rest <- lazyRead h
+ return (c : rest)
+
+ LineBuffering -> lazyReadBuffered h fd ref buf
+ BlockBuffering _ -> lazyReadBuffered h fd ref buf
+
+-- we never want to block during the read, so we call fillReadBuffer with
+-- is_line==True, which tells it to "just read what there is".
+lazyReadBuffered h fd ref buf = do
+ maybe_new_buf <-
+ if bufferEmpty buf
+ then maybeFillReadBuffer fd True buf
+ else return (Just buf)
+ case maybe_new_buf of
+ Nothing -> return ""
+ Just buf -> do
+ more <- lazyRead h
+ writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ unpackAcc (bufBuf buf) (bufRPtr buf) (bufWPtr buf) more
+
+
+maybeFillReadBuffer fd is_line buf
+ = catch
+ (do buf <- fillReadBuffer fd is_line buf
+ return (Just buf)
+ )
+ (\e -> if isEOFError e
+ then return Nothing
+ else throw e)
+
+
+unpackAcc :: RawBuffer -> Int -> Int -> [Char] -> IO [Char]
+unpackAcc buf r 0 acc = return ""
+unpackAcc buf (I## r) (I## len) acc = IO $ \s -> unpack acc (len -## 1##) s
+ where
+ unpack acc i s
+ | i <## r = (## s, acc ##)
+ | otherwise =
+ case readCharArray## buf i s of
+ (## s, ch ##) -> unpack (C## ch : acc) (i -## 1##) s
+
+-- ---------------------------------------------------------------------------
+-- hPutChar
+
+-- `hPutChar hdl ch' writes the character `ch' to the file or channel
+-- managed by `hdl'. Characters may be buffered if buffering is
+-- enabled for `hdl'.
+
+hPutChar :: Handle -> Char -> IO ()
+hPutChar handle c =
+ c `seq` do -- must evaluate c before grabbing the handle lock
+ wantWritableHandle "hPutChar" handle $ \ handle_ -> do
+ let fd = haFD handle_
+ case haBufferMode handle_ of
+ LineBuffering -> hPutcBuffered handle_ True c
+ BlockBuffering _ -> hPutcBuffered handle_ False c
+ NoBuffering ->
+ withObject (castCharToCChar c) $ \buf ->
+ throwErrnoIfMinus1RetryMayBlock_ "hPutChar"
+ (c_write (fromIntegral fd) buf 1)
+ (threadWaitWrite fd)
+
+
+hPutcBuffered handle_ is_line c = do
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+ let w = bufWPtr buf
+ w' <- writeCharIntoBuffer (bufBuf buf) w c
+ let new_buf = buf{ bufWPtr = w' }
+ if bufferFull new_buf || is_line && c == '\n'
+ then do
+ flushed_buf <- flushWriteBuffer (haFD handle_) new_buf
+ writeIORef ref flushed_buf
+ else do
+ writeIORef ref new_buf
+
+
+hPutChars :: Handle -> [Char] -> IO ()
+hPutChars handle [] = return ()
+hPutChars handle (c:cs) = hPutChar handle c >> hPutChars handle cs
+
+-- ---------------------------------------------------------------------------
+-- hPutStr
+
+-- `hPutStr hdl s' writes the string `s' to the file or
+-- hannel managed by `hdl', buffering the output if needs be.
+
+-- We go to some trouble to avoid keeping the handle locked while we're
+-- evaluating the string argument to hPutStr, in case doing so triggers another
+-- I/O operation on the same handle which would lead to deadlock. The classic
+-- case is
+--
+-- putStr (trace "hello" "world")
+--
+-- so the basic scheme is this:
+--
+-- * copy the string into a fresh buffer,
+-- * "commit" the buffer to the handle.
+--
+-- Committing may involve simply copying the contents of the new
+-- buffer into the handle's buffer, flushing one or both buffers, or
+-- maybe just swapping the buffers over (if the handle's buffer was
+-- empty). See commitBuffer below.
+
+hPutStr :: Handle -> String -> IO ()
+hPutStr handle str = do
+ buffer_mode <- wantWritableHandle "hPutStr" handle
+ (\ handle_ -> do getSpareBuffer handle_)
+ case buffer_mode of
+ (NoBuffering, _) -> do
+ hPutChars handle str -- v. slow, but we don't care
+ (LineBuffering, buf) -> do
+ writeLines handle buf str
+ (BlockBuffering _, buf) -> do
+ writeBlocks handle buf str
+
+
+getSpareBuffer :: Handle__ -> IO (BufferMode, Buffer)
+getSpareBuffer Handle__{haBuffer=ref,
+ haBuffers=spare_ref,
+ haBufferMode=mode}
+ = do
+ case mode of
+ NoBuffering -> return (mode, error "no buffer!")
+ _ -> do
+ bufs <- readIORef spare_ref
+ buf <- readIORef ref
+ case bufs of
+ BufferListCons b rest -> do
+ writeIORef spare_ref rest
+ return ( mode, newEmptyBuffer b WriteBuffer (bufSize buf))
+ BufferListNil -> do
+ new_buf <- allocateBuffer (bufSize buf) WriteBuffer
+ return (mode, new_buf)
+
+
+writeLines :: Handle -> Buffer -> String -> IO ()
+writeLines hdl Buffer{ bufBuf=raw, bufSize=len } s =
+ let
+ shoveString :: Int -> [Char] -> IO ()
+ -- check n == len first, to ensure that shoveString is strict in n.
+ shoveString n cs | n == len = do
+ new_buf <- commitBuffer hdl raw len n True{-needs flush-} False
+ writeBlocks hdl new_buf cs
+ shoveString n [] = do
+ commitBuffer hdl raw len n False{-no flush-} True{-release-}
+ return ()
+ shoveString n (c:cs) = do
+ n' <- writeCharIntoBuffer raw n c
+ shoveString n' cs
+ in
+ shoveString 0 s
+
+writeBlocks :: Handle -> Buffer -> String -> IO ()
+writeBlocks hdl Buffer{ bufBuf=raw, bufSize=len } s =
+ let
+ shoveString :: Int -> [Char] -> IO ()
+ -- check n == len first, to ensure that shoveString is strict in n.
+ shoveString n cs | n == len = do
+ new_buf <- commitBuffer hdl raw len n True{-needs flush-} False
+ writeBlocks hdl new_buf cs
+ shoveString n [] = do
+ commitBuffer hdl raw len n False{-no flush-} True{-release-}
+ return ()
+ shoveString n (c:cs) = do
+ n' <- writeCharIntoBuffer raw n c
+ shoveString n' cs
+ in
+ shoveString 0 s
+
+-- -----------------------------------------------------------------------------
+-- commitBuffer handle buf sz count flush release
+--
+-- Write the contents of the buffer 'buf' ('sz' bytes long, containing
+-- 'count' bytes of data) to handle (handle must be block or line buffered).
+--
+-- Implementation:
+--
+-- for block/line buffering,
+-- 1. If there isn't room in the handle buffer, flush the handle
+-- buffer.
+--
+-- 2. If the handle buffer is empty,
+-- if flush,
+-- then write buf directly to the device.
+-- else swap the handle buffer with buf.
+--
+-- 3. If the handle buffer is non-empty, copy buf into the
+-- handle buffer. Then, if flush != 0, flush
+-- the buffer.
+
+commitBuffer
+ :: Handle -- handle to commit to
+ -> RawBuffer -> Int -- address and size (in bytes) of buffer
+ -> Int -- number of bytes of data in buffer
+ -> Bool -- flush the handle afterward?
+ -> Bool -- release the buffer?
+ -> IO Buffer
+
+commitBuffer hdl raw sz count flush release = do
+ wantWritableHandle "commitAndReleaseBuffer" hdl $
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref, haBuffers=spare_buf_ref } -> do
+
+#ifdef DEBUG_DUMP
+ puts ("commitBuffer: sz=" ++ show sz ++ ", count=" ++ show count
+ ++ ", flush=" ++ show flush ++ ", release=" ++ show release ++"\n")
+#endif
+
+ old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
+ <- readIORef ref
+
+ buf_ret <-
+ -- enough room in handle buffer?
+ if (not flush && (size - w > count))
+ -- The > is to be sure that we never exactly fill
+ -- up the buffer, which would require a flush. So
+ -- if copying the new data into the buffer would
+ -- make the buffer full, we just flush the existing
+ -- buffer and the new data immediately, rather than
+ -- copying before flushing.
+
+ -- not flushing, and there's enough room in the buffer:
+ -- just copy the data in and update bufWPtr.
+ then do memcpy_baoff_ba old_raw w raw (fromIntegral count)
+ writeIORef ref old_buf{ bufWPtr = w + count }
+ return (newEmptyBuffer raw WriteBuffer sz)
+
+ -- else, we have to flush
+ else do flushed_buf <- flushWriteBuffer fd old_buf
+
+ let this_buf =
+ Buffer{ bufBuf=raw, bufState=WriteBuffer,
+ bufRPtr=0, bufWPtr=count, bufSize=sz }
+
+ -- if: (a) we don't have to flush, and
+ -- (b) size(new buffer) == size(old buffer), and
+ -- (c) new buffer is not full,
+ -- we can just just swap them over...
+ if (not flush && sz == size && count /= sz)
+ then do
+ writeIORef ref this_buf
+ return flushed_buf
+
+ -- otherwise, we have to flush the new data too,
+ -- and start with a fresh buffer
+ else do
+ flushWriteBuffer fd this_buf
+ writeIORef ref flushed_buf
+ -- if the sizes were different, then allocate
+ -- a new buffer of the correct size.
+ if sz == size
+ then return (newEmptyBuffer raw WriteBuffer sz)
+ else allocateBuffer size WriteBuffer
+
+ -- release the buffer if necessary
+ if release && bufSize buf_ret == size
+ then do
+ spare_bufs <- readIORef spare_buf_ref
+ writeIORef spare_buf_ref
+ (BufferListCons (bufBuf buf_ret) spare_bufs)
+ return buf_ret
+ else
+ return buf_ret
+
+-- ---------------------------------------------------------------------------
+-- Reading/writing sequences of bytes.
+
+{-
+Semantics of hGetBuf:
+
+ - hGetBuf reads data into the buffer until either
+
+ (a) EOF is reached
+ (b) the buffer is full
+
+ It returns the amount of data actually read. This may
+ be zero in case (a). hGetBuf never raises
+ an EOF exception, it always returns zero instead.
+
+ If the handle is a pipe or socket, and the writing end
+ is closed, hGetBuf will behave as for condition (a).
+
+Semantics of hPutBuf:
+
+ - hPutBuf writes data from the buffer to the handle
+ until the buffer is empty. It returns ().
+
+ If the handle is a pipe or socket, and the reading end is
+ closed, hPutBuf will raise a ResourceVanished exception.
+ (If this is a POSIX system, and the program has not
+ asked to ignore SIGPIPE, then a SIGPIPE may be delivered
+ instead, whose default action is to terminate the program).
+-}
+
+-- ---------------------------------------------------------------------------
+-- hPutBuf
+
+hPutBuf :: Handle -- handle to write to
+ -> Ptr a -- address of buffer
+ -> Int -- number of bytes of data in buffer
+ -> IO ()
+hPutBuf handle ptr count
+ | count <= 0 = illegalBufferSize handle "hPutBuf" count
+ | otherwise =
+ wantWritableHandle "hPutBuf" handle $
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+
+ old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
+ <- readIORef ref
+
+ -- enough room in handle buffer?
+ if (size - w > count)
+ -- There's enough room in the buffer:
+ -- just copy the data in and update bufWPtr.
+ then do memcpy_baoff_ptr old_raw w ptr (fromIntegral count)
+ writeIORef ref old_buf{ bufWPtr = w + count }
+ return ()
+
+ -- else, we have to flush
+ else do flushed_buf <- flushWriteBuffer fd old_buf
+ writeIORef ref flushed_buf
+ -- ToDo: should just memcpy instead of writing if possible
+ writeChunk fd ptr count
+
+writeChunk :: FD -> Ptr a -> Int -> IO ()
+writeChunk fd ptr bytes = loop 0 bytes
+ where
+ loop :: Int -> Int -> IO ()
+ loop _ bytes | bytes <= 0 = return ()
+ loop off bytes = do
+ r <- fromIntegral `liftM`
+ throwErrnoIfMinus1RetryMayBlock "writeChunk"
+ (c_write (fromIntegral fd) (ptr `plusPtr` off) (fromIntegral bytes))
+ (threadWaitWrite fd)
+ -- write can't return 0
+ loop (off + r) (bytes - r)
+
+-- ---------------------------------------------------------------------------
+-- hGetBuf
+
+hGetBuf :: Handle -> Ptr a -> Int -> IO Int
+hGetBuf handle ptr count
+ | count <= 0 = illegalBufferSize handle "hGetBuf" count
+ | otherwise =
+ wantReadableHandle "hGetBuf" handle $
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+ buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
+ if bufferEmpty buf
+ then readChunk fd ptr count
+ else do
+ let avail = w - r
+ copied <- if (count >= avail)
+ then do
+ memcpy_ptr_baoff ptr raw r (fromIntegral avail)
+ writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
+ return avail
+ else do
+ memcpy_ptr_baoff ptr raw r (fromIntegral count)
+ writeIORef ref buf{ bufRPtr = r + count }
+ return count
+
+ let remaining = count - copied
+ if remaining > 0
+ then do rest <- readChunk fd (ptr `plusPtr` copied) remaining
+ return (rest + count)
+ else return count
+
+readChunk :: FD -> Ptr a -> Int -> IO Int
+readChunk fd ptr bytes = loop 0 bytes
+ where
+ loop :: Int -> Int -> IO Int
+ loop off bytes | bytes <= 0 = return off
+ loop off bytes = do
+ r <- fromIntegral `liftM`
+ throwErrnoIfMinus1RetryMayBlock "readChunk"
+ (c_read (fromIntegral fd) (ptr `plusPtr` off) (fromIntegral bytes))
+ (threadWaitRead fd)
+ if r == 0
+ then return off
+ else loop (off + r) (bytes - r)
+
+slurpFile :: FilePath -> IO (Ptr (), Int)
+slurpFile fname = do
+ handle <- openFile fname ReadMode
+ sz <- hFileSize handle
+ if sz > fromIntegral (maxBound::Int) then
+ ioError (userError "slurpFile: file too big")
+ else do
+ let sz_i = fromIntegral sz
+ chunk <- mallocBytes sz_i
+ r <- hGetBuf handle chunk sz_i
+ hClose handle
+ return (chunk, r)
+
+-- ---------------------------------------------------------------------------
+-- hGetBufBA
+
+hGetBufBA :: Handle -> MutableByteArray RealWorld a -> Int -> IO Int
+hGetBufBA handle (MutableByteArray _ _ ptr) count
+ | count <= 0 = illegalBufferSize handle "hGetBuf" count
+ | otherwise =
+ wantReadableHandle "hGetBuf" handle $
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+ buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
+ if bufferEmpty buf
+ then readChunkBA fd ptr 0 count
+ else do
+ let avail = w - r
+ copied <- if (count >= avail)
+ then do
+ memcpy_ba_baoff ptr raw r (fromIntegral avail)
+ writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
+ return avail
+ else do
+ memcpy_ba_baoff ptr raw r (fromIntegral count)
+ writeIORef ref buf{ bufRPtr = r + count }
+ return count
+
+ let remaining = count - copied
+ if remaining > 0
+ then do rest <- readChunkBA fd ptr copied remaining
+ return (rest + count)
+ else return count
+
+readChunkBA :: FD -> RawBuffer -> Int -> Int -> IO Int
+readChunkBA fd ptr init_off bytes = loop init_off bytes
+ where
+ loop :: Int -> Int -> IO Int
+ loop off bytes | bytes <= 0 = return (off - init_off)
+ loop off bytes = do
+ r <- fromIntegral `liftM`
+ throwErrnoIfMinus1RetryMayBlock "readChunk"
+ (readBA (fromIntegral fd) ptr
+ (fromIntegral off) (fromIntegral bytes))
+ (threadWaitRead fd)
+ if r == 0
+ then return (off - init_off)
+ else loop (off + r) (bytes - r)
+
+foreign import "read_ba_wrap" unsafe
+ readBA :: FD -> RawBuffer -> Int -> CInt -> IO CInt
+#def inline \
+int read_ba_wrap(int fd, void *ptr, HsInt off, int size) \
+{ return read(fd, ptr + off, size); }
+
+-- -----------------------------------------------------------------------------
+-- hPutBufBA
+
+hPutBufBA
+ :: Handle -- handle to write to
+ -> MutableByteArray RealWorld a -- buffer
+ -> Int -- number of bytes of data in buffer
+ -> IO ()
+
+hPutBufBA handle (MutableByteArray _ _ raw) count
+ | count <= 0 = illegalBufferSize handle "hPutBufBA" count
+ | otherwise = do
+ wantWritableHandle "hPutBufBA" handle $
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+
+ old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
+ <- readIORef ref
+
+ -- enough room in handle buffer?
+ if (size - w > count)
+ -- There's enough room in the buffer:
+ -- just copy the data in and update bufWPtr.
+ then do memcpy_baoff_ba old_raw w raw (fromIntegral count)
+ writeIORef ref old_buf{ bufWPtr = w + count }
+ return ()
+
+ -- else, we have to flush
+ else do flushed_buf <- flushWriteBuffer fd old_buf
+ writeIORef ref flushed_buf
+ let this_buf =
+ Buffer{ bufBuf=raw, bufState=WriteBuffer,
+ bufRPtr=0, bufWPtr=count, bufSize=count }
+ flushWriteBuffer fd this_buf
+ return ()
+
+-- ---------------------------------------------------------------------------
+-- memcpy wrappers
+
+foreign import "memcpy_wrap_src_off" unsafe
+ memcpy_ba_baoff :: RawBuffer -> RawBuffer -> Int -> CSize -> IO (Ptr ())
+foreign import "memcpy_wrap_src_off" unsafe
+ memcpy_ptr_baoff :: Ptr a -> RawBuffer -> Int -> CSize -> IO (Ptr ())
+foreign import "memcpy_wrap_dst_off" unsafe
+ memcpy_baoff_ba :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())
+foreign import "memcpy_wrap_dst_off" unsafe
+ memcpy_baoff_ptr :: RawBuffer -> Int -> Ptr a -> CSize -> IO (Ptr ())
+
+#def inline \
+void *memcpy_wrap_dst_off(char *dst, int dst_off, char *src, size_t sz) \
+{ return memcpy(dst+dst_off, src, sz); }
+
+#def inline \
+void *memcpy_wrap_src_off(char *dst, char *src, int src_off, size_t sz) \
+{ return memcpy(dst, src+src_off, sz); }
+
+-----------------------------------------------------------------------------
+-- Internal Utils
+
+illegalBufferSize :: Handle -> String -> Int -> IO a
+illegalBufferSize handle fn (sz :: Int) =
+ ioException (IOError (Just handle)
+ InvalidArgument fn
+ ("illegal buffer size " ++ showsPrec 9 sz [])
+ Nothing)
diff --git a/libraries/base/GHC/IOBase.lhs b/libraries/base/GHC/IOBase.lhs
new file mode 100644
index 0000000000..7e77363424
--- /dev/null
+++ b/libraries/base/GHC/IOBase.lhs
@@ -0,0 +1,605 @@
+% ------------------------------------------------------------------------------
+% $Id: IOBase.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2001
+%
+
+% Definitions for the @IO@ monad and its friends. Everything is exported
+% concretely; the @IO@ module itself exports abstractly.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+#include "config.h"
+
+module GHC.IOBase where
+
+import GHC.ST
+import GHC.STRef
+import GHC.Arr
+import GHC.Base
+import GHC.Num -- To get fromInteger etc, needed because of -fno-implicit-prelude
+import GHC.Maybe ( Maybe(..) )
+import GHC.Show
+import GHC.List
+import GHC.Read
+import GHC.Dynamic
+
+-- ---------------------------------------------------------------------------
+-- The IO Monad
+
+{-
+The IO Monad is just an instance of the ST monad, where the state is
+the real world. We use the exception mechanism (in GHC.Exception) to
+implement IO exceptions.
+
+NOTE: The IO representation is deeply wired in to various parts of the
+system. The following list may or may not be exhaustive:
+
+Compiler - types of various primitives in PrimOp.lhs
+
+RTS - forceIO (StgMiscClosures.hc)
+ - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast
+ (Exceptions.hc)
+ - raiseAsync (Schedule.c)
+
+Prelude - GHC.IOBase.lhs, and several other places including
+ GHC.Exception.lhs.
+
+Libraries - parts of hslibs/lang.
+
+--SDM
+-}
+
+newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
+
+unIO :: IO a -> (State# RealWorld -> (# State# RealWorld, a #))
+unIO (IO a) = a
+
+instance Functor IO where
+ fmap f x = x >>= (return . f)
+
+instance Monad IO where
+ {-# INLINE return #-}
+ {-# INLINE (>>) #-}
+ {-# INLINE (>>=) #-}
+ m >> k = m >>= \ _ -> k
+ return x = returnIO x
+
+ m >>= k = bindIO m k
+ fail s = failIO s
+
+failIO :: String -> IO a
+failIO s = ioError (userError s)
+
+liftIO :: IO a -> State# RealWorld -> STret RealWorld a
+liftIO (IO m) = \s -> case m s of (# s', r #) -> STret s' r
+
+bindIO :: IO a -> (a -> IO b) -> IO b
+bindIO (IO m) k = IO ( \ s ->
+ case m s of
+ (# new_s, a #) -> unIO (k a) new_s
+ )
+
+returnIO :: a -> IO a
+returnIO x = IO (\ s -> (# s, x #))
+
+-- ---------------------------------------------------------------------------
+-- Coercions between IO and ST
+
+--stToIO :: (forall s. ST s a) -> IO a
+stToIO :: ST RealWorld a -> IO a
+stToIO (ST m) = IO m
+
+ioToST :: IO a -> ST RealWorld a
+ioToST (IO m) = (ST m)
+
+-- ---------------------------------------------------------------------------
+-- Unsafe IO operations
+
+{-# NOINLINE unsafePerformIO #-}
+unsafePerformIO :: IO a -> a
+unsafePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
+
+{-# NOINLINE unsafeInterleaveIO #-}
+unsafeInterleaveIO :: IO a -> IO a
+unsafeInterleaveIO (IO m)
+ = IO ( \ s -> let
+ r = case m s of (# _, res #) -> res
+ in
+ (# s, r #))
+
+-- ---------------------------------------------------------------------------
+-- Handle type
+
+data MVar a = MVar (MVar# RealWorld a)
+
+-- pull in Eq (Mvar a) too, to avoid GHC.Conc being an orphan-instance module
+instance Eq (MVar a) where
+ (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#
+
+-- A Handle is represented by (a reference to) a record
+-- containing the state of the I/O port/device. We record
+-- the following pieces of info:
+
+-- * type (read,write,closed etc.)
+-- * the underlying file descriptor
+-- * buffering mode
+-- * buffer, and spare buffers
+-- * user-friendly name (usually the
+-- FilePath used when IO.openFile was called)
+
+-- Note: when a Handle is garbage collected, we want to flush its buffer
+-- and close the OS file handle, so as to free up a (precious) resource.
+
+data Handle
+ = FileHandle -- A normal handle to a file
+ !(MVar Handle__)
+
+ | DuplexHandle -- A handle to a read/write stream
+ !(MVar Handle__) -- The read side
+ !(MVar Handle__) -- The write side
+
+-- NOTES:
+-- * A 'FileHandle' is seekable. A 'DuplexHandle' may or may not be
+-- seekable.
+
+instance Eq Handle where
+ (FileHandle h1) == (FileHandle h2) = h1 == h2
+ (DuplexHandle h1 _) == (DuplexHandle h2 _) = h1 == h2
+ _ == _ = False
+
+type FD = Int -- XXX ToDo: should be CInt
+
+data Handle__
+ = Handle__ {
+ haFD :: !FD,
+ haType :: HandleType,
+ haIsBin :: Bool,
+ haBufferMode :: BufferMode,
+ haFilePath :: FilePath,
+ haBuffer :: !(IORef Buffer),
+ haBuffers :: !(IORef BufferList)
+ }
+
+-- ---------------------------------------------------------------------------
+-- Buffers
+
+-- The buffer is represented by a mutable variable containing a
+-- record, where the record contains the raw buffer and the start/end
+-- points of the filled portion. We use a mutable variable so that
+-- the common operation of writing (or reading) some data from (to)
+-- the buffer doesn't need to modify, and hence copy, the handle
+-- itself, it just updates the buffer.
+
+-- There will be some allocation involved in a simple hPutChar in
+-- order to create the new Buffer structure (below), but this is
+-- relatively small, and this only has to be done once per write
+-- operation.
+
+-- The buffer contains its size - we could also get the size by
+-- calling sizeOfMutableByteArray# on the raw buffer, but that tends
+-- to be rounded up to the nearest Word.
+
+type RawBuffer = MutableByteArray# RealWorld
+
+-- INVARIANTS on a Buffer:
+--
+-- * A handle *always* has a buffer, even if it is only 1 character long
+-- (an unbuffered handle needs a 1 character buffer in order to support
+-- hLookAhead and hIsEOF).
+-- * r <= w
+-- * if r == w, then r == 0 && w == 0
+-- * if state == WriteBuffer, then r == 0
+-- * a write buffer is never full. If an operation
+-- fills up the buffer, it will always flush it before
+-- returning.
+-- * a read buffer may be full as a result of hLookAhead. In normal
+-- operation, a read buffer always has at least one character of space.
+
+data Buffer
+ = Buffer {
+ bufBuf :: RawBuffer,
+ bufRPtr :: !Int,
+ bufWPtr :: !Int,
+ bufSize :: !Int,
+ bufState :: BufferState
+ }
+
+data BufferState = ReadBuffer | WriteBuffer deriving (Eq)
+
+-- we keep a few spare buffers around in a handle to avoid allocating
+-- a new one for each hPutStr. These buffers are *guaranteed* to be the
+-- same size as the main buffer.
+data BufferList
+ = BufferListNil
+ | BufferListCons RawBuffer BufferList
+
+
+bufferIsWritable :: Buffer -> Bool
+bufferIsWritable Buffer{ bufState=WriteBuffer } = True
+bufferIsWritable _other = False
+
+bufferEmpty :: Buffer -> Bool
+bufferEmpty Buffer{ bufRPtr=r, bufWPtr=w } = r == w
+
+-- only makes sense for a write buffer
+bufferFull :: Buffer -> Bool
+bufferFull b@Buffer{ bufWPtr=w } = w >= bufSize b
+
+-- Internally, we classify handles as being one
+-- of the following:
+
+data HandleType
+ = ClosedHandle
+ | SemiClosedHandle
+ | ReadHandle
+ | WriteHandle
+ | AppendHandle
+ | ReadWriteHandle
+ | ReadSideHandle !(MVar Handle__) -- read side of a duplex handle
+
+isReadableHandleType ReadHandle = True
+isReadableHandleType ReadWriteHandle = True
+isReadableHandleType (ReadSideHandle _) = True
+isReadableHandleType _ = False
+
+isWritableHandleType AppendHandle = True
+isWritableHandleType WriteHandle = True
+isWritableHandleType ReadWriteHandle = True
+isWritableHandleType _ = False
+
+-- File names are specified using @FilePath@, a OS-dependent
+-- string that (hopefully, I guess) maps to an accessible file/object.
+
+type FilePath = String
+
+-- ---------------------------------------------------------------------------
+-- Buffering modes
+
+-- Three kinds of buffering are supported: line-buffering,
+-- block-buffering or no-buffering. These modes have the following
+-- effects. For output, items are written out from the internal
+-- buffer according to the buffer mode:
+--
+-- * line-buffering the entire output buffer is written
+-- out whenever a newline is output, the output buffer overflows,
+-- a flush is issued, or the handle is closed.
+--
+-- * block-buffering the entire output buffer is written out whenever
+-- it overflows, a flush is issued, or the handle
+-- is closed.
+--
+-- * no-buffering output is written immediately, and never stored
+-- in the output buffer.
+--
+-- The output buffer is emptied as soon as it has been written out.
+
+-- Similarly, input occurs according to the buffer mode for handle {\em hdl}.
+
+-- * line-buffering when the input buffer for the handle is not empty,
+-- the next item is obtained from the buffer;
+-- otherwise, when the input buffer is empty,
+-- characters up to and including the next newline
+-- character are read into the buffer. No characters
+-- are available until the newline character is
+-- available.
+--
+-- * block-buffering when the input buffer for the handle becomes empty,
+-- the next block of data is read into this buffer.
+--
+-- * no-buffering the next input item is read and returned.
+
+-- For most implementations, physical files will normally be block-buffered
+-- and terminals will normally be line-buffered. (the IO interface provides
+-- operations for changing the default buffering of a handle tho.)
+
+data BufferMode
+ = NoBuffering | LineBuffering | BlockBuffering (Maybe Int)
+ deriving (Eq, Ord, Read, Show)
+
+-- ---------------------------------------------------------------------------
+-- IORefs
+
+newtype IORef a = IORef (STRef RealWorld a) deriving Eq
+
+newIORef :: a -> IO (IORef a)
+newIORef v = stToIO (newSTRef v) >>= \ var -> return (IORef var)
+
+readIORef :: IORef a -> IO a
+readIORef (IORef var) = stToIO (readSTRef var)
+
+writeIORef :: IORef a -> a -> IO ()
+writeIORef (IORef var) v = stToIO (writeSTRef var v)
+
+-- ---------------------------------------------------------------------------
+-- Show instance for Handles
+
+-- handle types are 'show'n when printing error msgs, so
+-- we provide a more user-friendly Show instance for it
+-- than the derived one.
+
+instance Show HandleType where
+ showsPrec p t =
+ case t of
+ ClosedHandle -> showString "closed"
+ SemiClosedHandle -> showString "semi-closed"
+ ReadHandle -> showString "readable"
+ WriteHandle -> showString "writable"
+ AppendHandle -> showString "writable (append)"
+ ReadWriteHandle -> showString "read-writable"
+ ReadSideHandle _ -> showString "read-writable (duplex)"
+
+instance Show Handle where
+ showsPrec p (FileHandle h) = showHandle p h
+ showsPrec p (DuplexHandle h _) = showHandle p h
+
+showHandle p h =
+ let
+ -- (Big) SIGH: unfolded defn of takeMVar to avoid
+ -- an (oh-so) unfortunate module loop with GHC.Conc.
+ hdl_ = unsafePerformIO (IO $ \ s# ->
+ case h of { MVar h# ->
+ case takeMVar# h# s# of { (# s2# , r #) ->
+ case putMVar# h# r s2# of { s3# ->
+ (# s3#, r #) }}})
+ in
+ showChar '{' .
+ showHdl (haType hdl_)
+ (showString "loc=" . showString (haFilePath hdl_) . showChar ',' .
+ showString "type=" . showsPrec p (haType hdl_) . showChar ',' .
+ showString "binary=" . showsPrec p (haIsBin hdl_) . showChar ',' .
+ showString "buffering=" . showBufMode (unsafePerformIO (readIORef (haBuffer hdl_))) (haBufferMode hdl_) . showString "}" )
+ where
+ showHdl :: HandleType -> ShowS -> ShowS
+ showHdl ht cont =
+ case ht of
+ ClosedHandle -> showsPrec p ht . showString "}"
+ _ -> cont
+
+ showBufMode :: Buffer -> BufferMode -> ShowS
+ showBufMode buf bmo =
+ case bmo of
+ NoBuffering -> showString "none"
+ LineBuffering -> showString "line"
+ BlockBuffering (Just n) -> showString "block " . showParen True (showsPrec p n)
+ BlockBuffering Nothing -> showString "block " . showParen True (showsPrec p def)
+ where
+ def :: Int
+ def = bufSize buf
+
+-- ------------------------------------------------------------------------
+-- Exception datatype and operations
+
+data Exception
+ = IOException IOException -- IO exceptions
+ | ArithException ArithException -- Arithmetic exceptions
+ | ArrayException ArrayException -- Array-related exceptions
+ | ErrorCall String -- Calls to 'error'
+ | ExitException ExitCode -- Call to System.exitWith
+ | NoMethodError String -- A non-existent method was invoked
+ | PatternMatchFail String -- A pattern match / guard failure
+ | RecSelError String -- Selecting a non-existent field
+ | RecConError String -- Field missing in record construction
+ | RecUpdError String -- Record doesn't contain updated field
+ | AssertionFailed String -- Assertions
+ | DynException Dynamic -- Dynamic exceptions
+ | AsyncException AsyncException -- Externally generated errors
+ | BlockedOnDeadMVar -- Blocking on a dead MVar
+ | NonTermination
+ | UserError String
+
+data ArithException
+ = Overflow
+ | Underflow
+ | LossOfPrecision
+ | DivideByZero
+ | Denormal
+ deriving (Eq, Ord)
+
+data AsyncException
+ = StackOverflow
+ | HeapOverflow
+ | ThreadKilled
+ deriving (Eq, Ord)
+
+data ArrayException
+ = IndexOutOfBounds String -- out-of-range array access
+ | UndefinedElement String -- evaluating an undefined element
+ deriving (Eq, Ord)
+
+stackOverflow, heapOverflow :: Exception -- for the RTS
+stackOverflow = AsyncException StackOverflow
+heapOverflow = AsyncException HeapOverflow
+
+instance Show ArithException where
+ showsPrec _ Overflow = showString "arithmetic overflow"
+ showsPrec _ Underflow = showString "arithmetic underflow"
+ showsPrec _ LossOfPrecision = showString "loss of precision"
+ showsPrec _ DivideByZero = showString "divide by zero"
+ showsPrec _ Denormal = showString "denormal"
+
+instance Show AsyncException where
+ showsPrec _ StackOverflow = showString "stack overflow"
+ showsPrec _ HeapOverflow = showString "heap overflow"
+ showsPrec _ ThreadKilled = showString "thread killed"
+
+instance Show ArrayException where
+ showsPrec _ (IndexOutOfBounds s)
+ = showString "array index out of range"
+ . (if not (null s) then showString ": " . showString s
+ else id)
+ showsPrec _ (UndefinedElement s)
+ = showString "undefined array element"
+ . (if not (null s) then showString ": " . showString s
+ else id)
+
+instance Show Exception where
+ showsPrec _ (IOException err) = shows err
+ showsPrec _ (ArithException err) = shows err
+ showsPrec _ (ArrayException err) = shows err
+ showsPrec _ (ErrorCall err) = showString err
+ showsPrec _ (ExitException err) = showString "exit: " . shows err
+ showsPrec _ (NoMethodError err) = showString err
+ showsPrec _ (PatternMatchFail err) = showString err
+ showsPrec _ (RecSelError err) = showString err
+ showsPrec _ (RecConError err) = showString err
+ showsPrec _ (RecUpdError err) = showString err
+ showsPrec _ (AssertionFailed err) = showString err
+ showsPrec _ (DynException _err) = showString "unknown exception"
+ showsPrec _ (AsyncException e) = shows e
+ showsPrec _ (BlockedOnDeadMVar) = showString "thread blocked indefinitely"
+ showsPrec _ (NonTermination) = showString "<<loop>>"
+ showsPrec _ (UserError err) = showString err
+
+-- -----------------------------------------------------------------------------
+-- The ExitCode type
+
+-- The `ExitCode' type defines the exit codes that a program
+-- can return. `ExitSuccess' indicates successful termination;
+-- and `ExitFailure code' indicates program failure
+-- with value `code'. The exact interpretation of `code'
+-- is operating-system dependent. In particular, some values of
+-- `code' may be prohibited (e.g. 0 on a POSIX-compliant system).
+
+-- We need it here because it is used in ExitException in the
+-- Exception datatype (above).
+
+data ExitCode = ExitSuccess | ExitFailure Int
+ deriving (Eq, Ord, Read, Show)
+
+-- --------------------------------------------------------------------------
+-- Primitive throw
+
+throw :: Exception -> a
+throw exception = raise# exception
+
+ioError :: Exception -> IO a
+ioError err = IO $ \s -> throw err s
+
+ioException :: IOException -> IO a
+ioException err = IO $ \s -> throw (IOException err) s
+
+-- ---------------------------------------------------------------------------
+-- IOError type
+
+-- A value @IOError@ encode errors occurred in the @IO@ monad.
+-- An @IOError@ records a more specific error type, a descriptive
+-- string and maybe the handle that was used when the error was
+-- flagged.
+
+type IOError = Exception
+
+data IOException
+ = IOError
+ (Maybe Handle) -- the handle used by the action flagging the
+ -- the error.
+ IOErrorType -- what it was.
+ String -- location.
+ String -- error type specific information.
+ (Maybe FilePath) -- filename the error is related to.
+
+instance Eq IOException where
+ (IOError h1 e1 loc1 str1 fn1) == (IOError h2 e2 loc2 str2 fn2) =
+ e1==e2 && str1==str2 && h1==h2 && loc1==loc2 && fn1==fn2
+
+data IOErrorType
+ = AlreadyExists | HardwareFault
+ | IllegalOperation | InappropriateType
+ | Interrupted | InvalidArgument
+ | NoSuchThing | OtherError
+ | PermissionDenied | ProtocolError
+ | ResourceBusy | ResourceExhausted
+ | ResourceVanished | SystemError
+ | TimeExpired | UnsatisfiedConstraints
+ | UnsupportedOperation
+ | EOF
+#if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
+ | ComError Int -- HRESULT
+#endif
+ deriving (Eq)
+
+instance Show IOErrorType where
+ showsPrec _ e =
+ showString $
+ case e of
+ AlreadyExists -> "already exists"
+ HardwareFault -> "hardware fault"
+ IllegalOperation -> "illegal operation"
+ InappropriateType -> "inappropriate type"
+ Interrupted -> "interrupted"
+ InvalidArgument -> "invalid argument"
+ NoSuchThing -> "does not exist"
+ OtherError -> "failed"
+ PermissionDenied -> "permission denied"
+ ProtocolError -> "protocol error"
+ ResourceBusy -> "resource busy"
+ ResourceExhausted -> "resource exhausted"
+ ResourceVanished -> "resource vanished"
+ SystemError -> "system error"
+ TimeExpired -> "timeout"
+ UnsatisfiedConstraints -> "unsatisified constraints" -- ultra-precise!
+ UnsupportedOperation -> "unsupported operation"
+ EOF -> "end of file"
+#if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
+ ComError _ -> "COM error"
+#endif
+
+
+
+userError :: String -> IOError
+userError str = UserError str
+
+-- ---------------------------------------------------------------------------
+-- Predicates on IOError
+
+isAlreadyExistsError :: IOError -> Bool
+isAlreadyExistsError (IOException (IOError _ AlreadyExists _ _ _)) = True
+isAlreadyExistsError _ = False
+
+isAlreadyInUseError :: IOError -> Bool
+isAlreadyInUseError (IOException (IOError _ ResourceBusy _ _ _)) = True
+isAlreadyInUseError _ = False
+
+isFullError :: IOError -> Bool
+isFullError (IOException (IOError _ ResourceExhausted _ _ _)) = True
+isFullError _ = False
+
+isEOFError :: IOError -> Bool
+isEOFError (IOException (IOError _ EOF _ _ _)) = True
+isEOFError _ = False
+
+isIllegalOperation :: IOError -> Bool
+isIllegalOperation (IOException (IOError _ IllegalOperation _ _ _)) = True
+isIllegalOperation _ = False
+
+isPermissionError :: IOError -> Bool
+isPermissionError (IOException (IOError _ PermissionDenied _ _ _)) = True
+isPermissionError _ = False
+
+isDoesNotExistError :: IOError -> Bool
+isDoesNotExistError (IOException (IOError _ NoSuchThing _ _ _)) = True
+isDoesNotExistError _ = False
+
+isUserError :: IOError -> Bool
+isUserError (UserError _) = True
+isUserError _ = False
+
+-- ---------------------------------------------------------------------------
+-- Showing IOErrors
+
+instance Show IOException where
+ showsPrec p (IOError hdl iot loc s fn) =
+ showsPrec p iot .
+ (case loc of
+ "" -> id
+ _ -> showString "\nAction: " . showString loc) .
+ (case hdl of
+ Nothing -> id
+ Just h -> showString "\nHandle: " . showsPrec p h) .
+ (case s of
+ "" -> id
+ _ -> showString "\nReason: " . showString s) .
+ (case fn of
+ Nothing -> id
+ Just name -> showString "\nFile: " . showString name)
+\end{code}
diff --git a/libraries/base/GHC/Int.lhs b/libraries/base/GHC/Int.lhs
new file mode 100644
index 0000000000..c091d6759e
--- /dev/null
+++ b/libraries/base/GHC/Int.lhs
@@ -0,0 +1,599 @@
+%
+% (c) The University of Glasgow, 1997-2001
+%
+\section[GHC.Int]{Module @GHC.Int@}
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#include "MachDeps.h"
+
+module GHC.Int (
+ Int8(..), Int16(..), Int32(..), Int64(..))
+ where
+
+import Data.Bits
+
+import GHC.Base
+import GHC.Enum
+import GHC.Num
+import GHC.Real
+import GHC.Read
+import GHC.Arr
+import GHC.Word
+import GHC.Show
+
+------------------------------------------------------------------------
+-- type Int8
+------------------------------------------------------------------------
+
+-- Int8 is represented in the same way as Int. Operations may assume
+-- and must ensure that it holds only values from its logical range.
+
+data Int8 = I8# Int# deriving (Eq, Ord)
+
+instance CCallable Int8
+instance CReturnable Int8
+
+instance Show Int8 where
+ showsPrec p x = showsPrec p (fromIntegral x :: Int)
+
+instance Num Int8 where
+ (I8# x#) + (I8# y#) = I8# (intToInt8# (x# +# y#))
+ (I8# x#) - (I8# y#) = I8# (intToInt8# (x# -# y#))
+ (I8# x#) * (I8# y#) = I8# (intToInt8# (x# *# y#))
+ negate (I8# x#) = I8# (intToInt8# (negateInt# x#))
+ abs x | x >= 0 = x
+ | otherwise = negate x
+ signum x | x > 0 = 1
+ signum 0 = 0
+ signum _ = -1
+ fromInteger (S# i#) = I8# (intToInt8# i#)
+ fromInteger (J# s# d#) = I8# (intToInt8# (integer2Int# s# d#))
+
+instance Real Int8 where
+ toRational x = toInteger x % 1
+
+instance Enum Int8 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Int8"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Int8"
+ toEnum i@(I# i#)
+ | i >= fromIntegral (minBound::Int8) && i <= fromIntegral (maxBound::Int8)
+ = I8# i#
+ | otherwise = toEnumError "Int8" i (minBound::Int8, maxBound::Int8)
+ fromEnum (I8# x#) = I# x#
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+
+instance Integral Int8 where
+ quot x@(I8# x#) y@(I8# y#)
+ | y /= 0 = I8# (intToInt8# (x# `quotInt#` y#))
+ | otherwise = divZeroError "quot{Int8}" x
+ rem x@(I8# x#) y@(I8# y#)
+ | y /= 0 = I8# (intToInt8# (x# `remInt#` y#))
+ | otherwise = divZeroError "rem{Int8}" x
+ div x@(I8# x#) y@(I8# y#)
+ | y /= 0 = I8# (intToInt8# (x# `divInt#` y#))
+ | otherwise = divZeroError "div{Int8}" x
+ mod x@(I8# x#) y@(I8# y#)
+ | y /= 0 = I8# (intToInt8# (x# `modInt#` y#))
+ | otherwise = divZeroError "mod{Int8}" x
+ quotRem x@(I8# x#) y@(I8# y#)
+ | y /= 0 = (I8# (intToInt8# (x# `quotInt#` y#)),
+ I8# (intToInt8# (x# `remInt#` y#)))
+ | otherwise = divZeroError "quotRem{Int8}" x
+ divMod x@(I8# x#) y@(I8# y#)
+ | y /= 0 = (I8# (intToInt8# (x# `divInt#` y#)),
+ I8# (intToInt8# (x# `modInt#` y#)))
+ | otherwise = divZeroError "divMod{Int8}" x
+ toInteger (I8# x#) = S# x#
+
+instance Bounded Int8 where
+ minBound = -0x80
+ maxBound = 0x7F
+
+instance Ix Int8 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Int8"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Int8 where
+ readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]
+
+instance Bits Int8 where
+ (I8# x#) .&. (I8# y#) = I8# (word2Int# (int2Word# x# `and#` int2Word# y#))
+ (I8# x#) .|. (I8# y#) = I8# (word2Int# (int2Word# x# `or#` int2Word# y#))
+ (I8# x#) `xor` (I8# y#) = I8# (word2Int# (int2Word# x# `xor#` int2Word# y#))
+ complement (I8# x#) = I8# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))
+ (I8# x#) `shift` (I# i#)
+ | i# >=# 0# = I8# (intToInt8# (x# `iShiftL#` i#))
+ | otherwise = I8# (x# `iShiftRA#` negateInt# i#)
+ (I8# x#) `rotate` (I# i#) =
+ I8# (intToInt8# (word2Int# ((x'# `shiftL#` i'#) `or#`
+ (x'# `shiftRL#` (8# -# i'#)))))
+ where
+ x'# = wordToWord8# (int2Word# x#)
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 7#)
+ bitSize _ = 8
+ isSigned _ = True
+
+{-# RULES
+"fromIntegral/Int8->Int8" fromIntegral = id :: Int8 -> Int8
+"fromIntegral/a->Int8" fromIntegral = \x -> case fromIntegral x of I# x# -> I8# (intToInt8# x#)
+"fromIntegral/Int8->a" fromIntegral = \(I8# x#) -> fromIntegral (I# x#)
+ #-}
+
+------------------------------------------------------------------------
+-- type Int16
+------------------------------------------------------------------------
+
+-- Int16 is represented in the same way as Int. Operations may assume
+-- and must ensure that it holds only values from its logical range.
+
+data Int16 = I16# Int# deriving (Eq, Ord)
+
+instance CCallable Int16
+instance CReturnable Int16
+
+instance Show Int16 where
+ showsPrec p x = showsPrec p (fromIntegral x :: Int)
+
+instance Num Int16 where
+ (I16# x#) + (I16# y#) = I16# (intToInt16# (x# +# y#))
+ (I16# x#) - (I16# y#) = I16# (intToInt16# (x# -# y#))
+ (I16# x#) * (I16# y#) = I16# (intToInt16# (x# *# y#))
+ negate (I16# x#) = I16# (intToInt16# (negateInt# x#))
+ abs x | x >= 0 = x
+ | otherwise = negate x
+ signum x | x > 0 = 1
+ signum 0 = 0
+ signum _ = -1
+ fromInteger (S# i#) = I16# (intToInt16# i#)
+ fromInteger (J# s# d#) = I16# (intToInt16# (integer2Int# s# d#))
+
+instance Real Int16 where
+ toRational x = toInteger x % 1
+
+instance Enum Int16 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Int16"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Int16"
+ toEnum i@(I# i#)
+ | i >= fromIntegral (minBound::Int16) && i <= fromIntegral (maxBound::Int16)
+ = I16# i#
+ | otherwise = toEnumError "Int16" i (minBound::Int16, maxBound::Int16)
+ fromEnum (I16# x#) = I# x#
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+
+instance Integral Int16 where
+ quot x@(I16# x#) y@(I16# y#)
+ | y /= 0 = I16# (intToInt16# (x# `quotInt#` y#))
+ | otherwise = divZeroError "quot{Int16}" x
+ rem x@(I16# x#) y@(I16# y#)
+ | y /= 0 = I16# (intToInt16# (x# `remInt#` y#))
+ | otherwise = divZeroError "rem{Int16}" x
+ div x@(I16# x#) y@(I16# y#)
+ | y /= 0 = I16# (intToInt16# (x# `divInt#` y#))
+ | otherwise = divZeroError "div{Int16}" x
+ mod x@(I16# x#) y@(I16# y#)
+ | y /= 0 = I16# (intToInt16# (x# `modInt#` y#))
+ | otherwise = divZeroError "mod{Int16}" x
+ quotRem x@(I16# x#) y@(I16# y#)
+ | y /= 0 = (I16# (intToInt16# (x# `quotInt#` y#)),
+ I16# (intToInt16# (x# `remInt#` y#)))
+ | otherwise = divZeroError "quotRem{Int16}" x
+ divMod x@(I16# x#) y@(I16# y#)
+ | y /= 0 = (I16# (intToInt16# (x# `divInt#` y#)),
+ I16# (intToInt16# (x# `modInt#` y#)))
+ | otherwise = divZeroError "divMod{Int16}" x
+ toInteger (I16# x#) = S# x#
+
+instance Bounded Int16 where
+ minBound = -0x8000
+ maxBound = 0x7FFF
+
+instance Ix Int16 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Int16"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Int16 where
+ readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]
+
+instance Bits Int16 where
+ (I16# x#) .&. (I16# y#) = I16# (word2Int# (int2Word# x# `and#` int2Word# y#))
+ (I16# x#) .|. (I16# y#) = I16# (word2Int# (int2Word# x# `or#` int2Word# y#))
+ (I16# x#) `xor` (I16# y#) = I16# (word2Int# (int2Word# x# `xor#` int2Word# y#))
+ complement (I16# x#) = I16# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))
+ (I16# x#) `shift` (I# i#)
+ | i# >=# 0# = I16# (intToInt16# (x# `iShiftL#` i#))
+ | otherwise = I16# (x# `iShiftRA#` negateInt# i#)
+ (I16# x#) `rotate` (I# i#) =
+ I16# (intToInt16# (word2Int# ((x'# `shiftL#` i'#) `or#`
+ (x'# `shiftRL#` (16# -# i'#)))))
+ where
+ x'# = wordToWord16# (int2Word# x#)
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 15#)
+ bitSize _ = 16
+ isSigned _ = True
+
+{-# RULES
+"fromIntegral/Word8->Int16" fromIntegral = \(W8# x#) -> I16# (word2Int# x#)
+"fromIntegral/Int8->Int16" fromIntegral = \(I8# x#) -> I16# x#
+"fromIntegral/Int16->Int16" fromIntegral = id :: Int16 -> Int16
+"fromIntegral/a->Int16" fromIntegral = \x -> case fromIntegral x of I# x# -> I16# (intToInt16# x#)
+"fromIntegral/Int16->a" fromIntegral = \(I16# x#) -> fromIntegral (I# x#)
+ #-}
+
+------------------------------------------------------------------------
+-- type Int32
+------------------------------------------------------------------------
+
+-- Int32 is represented in the same way as Int.
+#if WORD_SIZE_IN_BYTES == 8
+-- Operations may assume and must ensure that it holds only values
+-- from its logical range.
+#endif
+
+data Int32 = I32# Int# deriving (Eq, Ord)
+
+instance CCallable Int32
+instance CReturnable Int32
+
+instance Show Int32 where
+ showsPrec p x = showsPrec p (fromIntegral x :: Int)
+
+instance Num Int32 where
+ (I32# x#) + (I32# y#) = I32# (intToInt32# (x# +# y#))
+ (I32# x#) - (I32# y#) = I32# (intToInt32# (x# -# y#))
+ (I32# x#) * (I32# y#) = I32# (intToInt32# (x# *# y#))
+ negate (I32# x#) = I32# (intToInt32# (negateInt# x#))
+ abs x | x >= 0 = x
+ | otherwise = negate x
+ signum x | x > 0 = 1
+ signum 0 = 0
+ signum _ = -1
+ fromInteger (S# i#) = I32# (intToInt32# i#)
+ fromInteger (J# s# d#) = I32# (intToInt32# (integer2Int# s# d#))
+
+instance Real Int32 where
+ toRational x = toInteger x % 1
+
+instance Enum Int32 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Int32"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Int32"
+#if WORD_SIZE_IN_BYTES == 4
+ toEnum (I# i#) = I32# i#
+#else
+ toEnum i@(I# i#)
+ | i >= fromIntegral (minBound::Int32) && i <= fromIntegral (maxBound::Int32)
+ = I32# i#
+ | otherwise = toEnumError "Int32" i (minBound::Int32, maxBound::Int32)
+#endif
+ fromEnum (I32# x#) = I# x#
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+
+instance Integral Int32 where
+ quot x@(I32# x#) y@(I32# y#)
+ | y /= 0 = I32# (intToInt32# (x# `quotInt#` y#))
+ | otherwise = divZeroError "quot{Int32}" x
+ rem x@(I32# x#) y@(I32# y#)
+ | y /= 0 = I32# (intToInt32# (x# `remInt#` y#))
+ | otherwise = divZeroError "rem{Int32}" x
+ div x@(I32# x#) y@(I32# y#)
+ | y /= 0 = I32# (intToInt32# (x# `divInt#` y#))
+ | otherwise = divZeroError "div{Int32}" x
+ mod x@(I32# x#) y@(I32# y#)
+ | y /= 0 = I32# (intToInt32# (x# `modInt#` y#))
+ | otherwise = divZeroError "mod{Int32}" x
+ quotRem x@(I32# x#) y@(I32# y#)
+ | y /= 0 = (I32# (intToInt32# (x# `quotInt#` y#)),
+ I32# (intToInt32# (x# `remInt#` y#)))
+ | otherwise = divZeroError "quotRem{Int32}" x
+ divMod x@(I32# x#) y@(I32# y#)
+ | y /= 0 = (I32# (intToInt32# (x# `divInt#` y#)),
+ I32# (intToInt32# (x# `modInt#` y#)))
+ | otherwise = divZeroError "divMod{Int32}" x
+ toInteger (I32# x#) = S# x#
+
+instance Bounded Int32 where
+ minBound = -0x80000000
+ maxBound = 0x7FFFFFFF
+
+instance Ix Int32 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Int32"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Int32 where
+ readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]
+
+instance Bits Int32 where
+ (I32# x#) .&. (I32# y#) = I32# (word2Int# (int2Word# x# `and#` int2Word# y#))
+ (I32# x#) .|. (I32# y#) = I32# (word2Int# (int2Word# x# `or#` int2Word# y#))
+ (I32# x#) `xor` (I32# y#) = I32# (word2Int# (int2Word# x# `xor#` int2Word# y#))
+ complement (I32# x#) = I32# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))
+ (I32# x#) `shift` (I# i#)
+ | i# >=# 0# = I32# (intToInt32# (x# `iShiftL#` i#))
+ | otherwise = I32# (x# `iShiftRA#` negateInt# i#)
+ (I32# x#) `rotate` (I# i#) =
+ I32# (intToInt32# (word2Int# ((x'# `shiftL#` i'#) `or#`
+ (x'# `shiftRL#` (32# -# i'#)))))
+ where
+ x'# = wordToWord32# (int2Word# x#)
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 31#)
+ bitSize _ = 32
+ isSigned _ = True
+
+{-# RULES
+"fromIntegral/Word8->Int32" fromIntegral = \(W8# x#) -> I32# (word2Int# x#)
+"fromIntegral/Word16->Int32" fromIntegral = \(W16# x#) -> I32# (word2Int# x#)
+"fromIntegral/Int8->Int32" fromIntegral = \(I8# x#) -> I32# x#
+"fromIntegral/Int16->Int32" fromIntegral = \(I16# x#) -> I32# x#
+"fromIntegral/Int32->Int32" fromIntegral = id :: Int32 -> Int32
+"fromIntegral/a->Int32" fromIntegral = \x -> case fromIntegral x of I# x# -> I32# (intToInt32# x#)
+"fromIntegral/Int32->a" fromIntegral = \(I32# x#) -> fromIntegral (I# x#)
+ #-}
+
+------------------------------------------------------------------------
+-- type Int64
+------------------------------------------------------------------------
+
+#if WORD_SIZE_IN_BYTES == 4
+
+data Int64 = I64# Int64#
+
+instance Eq Int64 where
+ (I64# x#) == (I64# y#) = x# `eqInt64#` y#
+ (I64# x#) /= (I64# y#) = x# `neInt64#` y#
+
+instance Ord Int64 where
+ (I64# x#) < (I64# y#) = x# `ltInt64#` y#
+ (I64# x#) <= (I64# y#) = x# `leInt64#` y#
+ (I64# x#) > (I64# y#) = x# `gtInt64#` y#
+ (I64# x#) >= (I64# y#) = x# `geInt64#` y#
+
+instance Show Int64 where
+ showsPrec p x = showsPrec p (toInteger x)
+
+instance Num Int64 where
+ (I64# x#) + (I64# y#) = I64# (x# `plusInt64#` y#)
+ (I64# x#) - (I64# y#) = I64# (x# `minusInt64#` y#)
+ (I64# x#) * (I64# y#) = I64# (x# `timesInt64#` y#)
+ negate (I64# x#) = I64# (negateInt64# x#)
+ abs x | x >= 0 = x
+ | otherwise = negate x
+ signum x | x > 0 = 1
+ signum 0 = 0
+ signum _ = -1
+ fromInteger (S# i#) = I64# (intToInt64# i#)
+ fromInteger (J# s# d#) = I64# (integerToInt64# s# d#)
+
+instance Enum Int64 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Int64"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Int64"
+ toEnum (I# i#) = I64# (intToInt64# i#)
+ fromEnum x@(I64# x#)
+ | x >= fromIntegral (minBound::Int) && x <= fromIntegral (maxBound::Int)
+ = I# (int64ToInt# x#)
+ | otherwise = fromEnumError "Int64" x
+ enumFrom = integralEnumFrom
+ enumFromThen = integralEnumFromThen
+ enumFromTo = integralEnumFromTo
+ enumFromThenTo = integralEnumFromThenTo
+
+instance Integral Int64 where
+ quot x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `quotInt64#` y#)
+ | otherwise = divZeroError "quot{Int64}" x
+ rem x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `remInt64#` y#)
+ | otherwise = divZeroError "rem{Int64}" x
+ div x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `divInt64#` y#)
+ | otherwise = divZeroError "div{Int64}" x
+ mod x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `modInt64#` y#)
+ | otherwise = divZeroError "mod{Int64}" x
+ quotRem x@(I64# x#) y@(I64# y#)
+ | y /= 0 = (I64# (x# `quotInt64#` y#), I64# (x# `remInt64#` y#))
+ | otherwise = divZeroError "quotRem{Int64}" x
+ divMod x@(I64# x#) y@(I64# y#)
+ | y /= 0 = (I64# (x# `divInt64#` y#), I64# (x# `modInt64#` y#))
+ | otherwise = divZeroError "divMod{Int64}" x
+ toInteger x@(I64# x#)
+ | x >= -0x80000000 && x <= 0x7FFFFFFF
+ = S# (int64ToInt# x#)
+ | otherwise = case int64ToInteger# x# of (# s, d #) -> J# s d
+
+divInt64#, modInt64# :: Int64# -> Int64# -> Int64#
+x# `divInt64#` y#
+ | (x# `gtInt64#` intToInt64# 0#) && (y# `ltInt64#` intToInt64# 0#)
+ = ((x# `minusInt64#` y#) `minusInt64#` intToInt64# 1#) `quotInt64#` y#
+ | (x# `ltInt64#` intToInt64# 0#) && (y# `gtInt64#` intToInt64# 0#)
+ = ((x# `minusInt64#` y#) `plusInt64#` intToInt64# 1#) `quotInt64#` y#
+ | otherwise = x# `quotInt64#` y#
+x# `modInt64#` y#
+ | (x# `gtInt64#` intToInt64# 0#) && (y# `ltInt64#` intToInt64# 0#) ||
+ (x# `ltInt64#` intToInt64# 0#) && (y# `gtInt64#` intToInt64# 0#)
+ = if r# `neInt64#` intToInt64# 0# then r# `plusInt64#` y# else intToInt64# 0#
+ | otherwise = r#
+ where
+ r# = x# `remInt64#` y#
+
+instance Read Int64 where
+ readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]
+
+instance Bits Int64 where
+ (I64# x#) .&. (I64# y#) = I64# (word64ToInt64# (int64ToWord64# x# `and64#` int64ToWord64# y#))
+ (I64# x#) .|. (I64# y#) = I64# (word64ToInt64# (int64ToWord64# x# `or64#` int64ToWord64# y#))
+ (I64# x#) `xor` (I64# y#) = I64# (word64ToInt64# (int64ToWord64# x# `xor64#` int64ToWord64# y#))
+ complement (I64# x#) = I64# (word64ToInt64# (not64# (int64ToWord64# x#)))
+ (I64# x#) `shift` (I# i#)
+ | i# >=# 0# = I64# (x# `iShiftL64#` i#)
+ | otherwise = I64# (x# `iShiftRA64#` negateInt# i#)
+ (I64# x#) `rotate` (I# i#) =
+ I64# (word64ToInt64# ((x'# `shiftL64#` i'#) `or64#`
+ (x'# `shiftRL64#` (64# -# i'#))))
+ where
+ x'# = int64ToWord64# x#
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)
+ bitSize _ = 64
+ isSigned _ = True
+
+foreign import "stg_eqInt64" unsafe eqInt64# :: Int64# -> Int64# -> Bool
+foreign import "stg_neInt64" unsafe neInt64# :: Int64# -> Int64# -> Bool
+foreign import "stg_ltInt64" unsafe ltInt64# :: Int64# -> Int64# -> Bool
+foreign import "stg_leInt64" unsafe leInt64# :: Int64# -> Int64# -> Bool
+foreign import "stg_gtInt64" unsafe gtInt64# :: Int64# -> Int64# -> Bool
+foreign import "stg_geInt64" unsafe geInt64# :: Int64# -> Int64# -> Bool
+foreign import "stg_plusInt64" unsafe plusInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_minusInt64" unsafe minusInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_timesInt64" unsafe timesInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_negateInt64" unsafe negateInt64# :: Int64# -> Int64#
+foreign import "stg_quotInt64" unsafe quotInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_remInt64" unsafe remInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_intToInt64" unsafe intToInt64# :: Int# -> Int64#
+foreign import "stg_int64ToInt" unsafe int64ToInt# :: Int64# -> Int#
+foreign import "stg_wordToWord64" unsafe wordToWord64# :: Word# -> Word64#
+foreign import "stg_int64ToWord64" unsafe int64ToWord64# :: Int64# -> Word64#
+foreign import "stg_word64ToInt64" unsafe word64ToInt64# :: Word64# -> Int64#
+foreign import "stg_and64" unsafe and64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_or64" unsafe or64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_xor64" unsafe xor64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_not64" unsafe not64# :: Word64# -> Word64#
+foreign import "stg_iShiftL64" unsafe iShiftL64# :: Int64# -> Int# -> Int64#
+foreign import "stg_iShiftRA64" unsafe iShiftRA64# :: Int64# -> Int# -> Int64#
+foreign import "stg_shiftL64" unsafe shiftL64# :: Word64# -> Int# -> Word64#
+foreign import "stg_shiftRL64" unsafe shiftRL64# :: Word64# -> Int# -> Word64#
+
+{-# RULES
+"fromIntegral/Int->Int64" fromIntegral = \(I# x#) -> I64# (intToInt64# x#)
+"fromIntegral/Word->Int64" fromIntegral = \(W# x#) -> I64# (word64ToInt64# (wordToWord64# x#))
+"fromIntegral/Word64->Int64" fromIntegral = \(W64# x#) -> I64# (word64ToInt64# x#)
+"fromIntegral/Int64->Int" fromIntegral = \(I64# x#) -> I# (int64ToInt# x#)
+"fromIntegral/Int64->Word" fromIntegral = \(I64# x#) -> W# (int2Word# (int64ToInt# x#))
+"fromIntegral/Int64->Word64" fromIntegral = \(I64# x#) -> W64# (int64ToWord64# x#)
+"fromIntegral/Int64->Int64" fromIntegral = id :: Int64 -> Int64
+ #-}
+
+#else
+
+data Int64 = I64# Int# deriving (Eq, Ord)
+
+instance Show Int64 where
+ showsPrec p x = showsPrec p (fromIntegral x :: Int)
+
+instance Num Int64 where
+ (I64# x#) + (I64# y#) = I64# (x# +# y#)
+ (I64# x#) - (I64# y#) = I64# (x# -# y#)
+ (I64# x#) * (I64# y#) = I64# (x# *# y#)
+ negate (I64# x#) = I64# (negateInt# x#)
+ abs x | x >= 0 = x
+ | otherwise = negate x
+ signum x | x > 0 = 1
+ signum 0 = 0
+ signum _ = -1
+ fromInteger (S# i#) = I64# i#
+ fromInteger (J# s# d#) = I64# (integer2Int# s# d#)
+
+instance Enum Int64 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Int64"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Int64"
+ toEnum (I# i#) = I64# i#
+ fromEnum (I64# x#) = I# x#
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+
+instance Integral Int64 where
+ quot x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `quotInt#` y#)
+ | otherwise = divZeroError "quot{Int64}" x
+ rem x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `remInt#` y#)
+ | otherwise = divZeroError "rem{Int64}" x
+ div x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `divInt#` y#)
+ | otherwise = divZeroError "div{Int64}" x
+ mod x@(I64# x#) y@(I64# y#)
+ | y /= 0 = I64# (x# `modInt#` y#)
+ | otherwise = divZeroError "mod{Int64}" x
+ quotRem x@(I64# x#) y@(I64# y#)
+ | y /= 0 = (I64# (x# `quotInt#` y#), I64# (x# `remInt#` y#))
+ | otherwise = divZeroError "quotRem{Int64}" x
+ divMod x@(I64# x#) y@(I64# y#)
+ | y /= 0 = (I64# (x# `divInt#` y#), I64# (x# `modInt#` y#))
+ | otherwise = divZeroError "divMod{Int64}" x
+ toInteger (I64# x#) = S# x#
+
+instance Read Int64 where
+ readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]
+
+instance Bits Int64 where
+ (I64# x#) .&. (I64# y#) = I64# (word2Int# (int2Word# x# `and#` int2Word# y#))
+ (I64# x#) .|. (I64# y#) = I64# (word2Int# (int2Word# x# `or#` int2Word# y#))
+ (I64# x#) `xor` (I64# y#) = I64# (word2Int# (int2Word# x# `xor#` int2Word# y#))
+ complement (I64# x#) = I64# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))
+ (I64# x#) `shift` (I# i#)
+ | i# >=# 0# = I64# (x# `iShiftL#` i#)
+ | otherwise = I64# (x# `iShiftRA#` negateInt# i#)
+ (I64# x#) `rotate` (I# i#) =
+ I64# (word2Int# ((x'# `shiftL#` i'#) `or#`
+ (x'# `shiftRL#` (64# -# i'#))))
+ where
+ x'# = int2Word# x#
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)
+ bitSize _ = 64
+ isSigned _ = True
+
+{-# RULES
+"fromIntegral/a->Int64" fromIntegral = \x -> case fromIntegral x of I# x# -> I64# (intToInt64# x#)
+"fromIntegral/Int64->a" fromIntegral = \(I64# x#) -> fromIntegral (I# x#)
+ #-}
+
+#endif
+
+instance CCallable Int64
+instance CReturnable Int64
+
+instance Real Int64 where
+ toRational x = toInteger x % 1
+
+instance Bounded Int64 where
+ minBound = -0x8000000000000000
+ maxBound = 0x7FFFFFFFFFFFFFFF
+
+instance Ix Int64 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Int64"
+ inRange (m,n) i = m <= i && i <= n
+\end{code}
diff --git a/libraries/base/GHC/List.lhs b/libraries/base/GHC/List.lhs
new file mode 100644
index 0000000000..c054bdb3d4
--- /dev/null
+++ b/libraries/base/GHC/List.lhs
@@ -0,0 +1,610 @@
+% ------------------------------------------------------------------------------
+% $Id: List.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.List]{Module @GHC.List@}
+
+The List data type and its operations
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.List (
+ [] (..),
+
+ map, (++), filter, concat,
+ head, last, tail, init, null, length, (!!),
+ foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1,
+ iterate, repeat, replicate, cycle,
+ take, drop, splitAt, takeWhile, dropWhile, span, break,
+ reverse, and, or,
+ any, all, elem, notElem, lookup,
+ maximum, minimum, concatMap,
+ zip, zip3, zipWith, zipWith3, unzip, unzip3,
+#ifdef USE_REPORT_PRELUDE
+
+#else
+
+ -- non-standard, but hidden when creating the Prelude
+ -- export list.
+ takeUInt_append
+
+#endif
+
+ ) where
+
+import {-# SOURCE #-} GHC.Err ( error )
+import GHC.Tup
+import GHC.Maybe
+import GHC.Base
+
+infixl 9 !!
+infix 4 `elem`, `notElem`
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{List-manipulation functions}
+%* *
+%*********************************************************
+
+\begin{code}
+-- head and tail extract the first element and remaining elements,
+-- respectively, of a list, which must be non-empty. last and init
+-- are the dual functions working from the end of a finite list,
+-- rather than the beginning.
+
+head :: [a] -> a
+head (x:_) = x
+head [] = badHead
+
+badHead = errorEmptyList "head"
+
+-- This rule is useful in cases like
+-- head [y | (x,y) <- ps, x==t]
+{-# RULES
+"head/build" forall (g::forall b.(Bool->b->b)->b->b) .
+ head (build g) = g (\x _ -> x) badHead
+"head/augment" forall xs (g::forall b. (a->b->b) -> b -> b) .
+ head (augment g xs) = g (\x _ -> x) (head xs)
+ #-}
+
+tail :: [a] -> [a]
+tail (_:xs) = xs
+tail [] = errorEmptyList "tail"
+
+last :: [a] -> a
+#ifdef USE_REPORT_PRELUDE
+last [x] = x
+last (_:xs) = last xs
+last [] = errorEmptyList "last"
+#else
+-- eliminate repeated cases
+last [] = errorEmptyList "last"
+last (x:xs) = last' x xs
+ where last' y [] = y
+ last' _ (y:ys) = last' y ys
+#endif
+
+init :: [a] -> [a]
+#ifdef USE_REPORT_PRELUDE
+init [x] = []
+init (x:xs) = x : init xs
+init [] = errorEmptyList "init"
+#else
+-- eliminate repeated cases
+init [] = errorEmptyList "init"
+init (x:xs) = init' x xs
+ where init' _ [] = []
+ init' y (z:zs) = y : init' z zs
+#endif
+
+null :: [a] -> Bool
+null [] = True
+null (_:_) = False
+
+-- length returns the length of a finite list as an Int; it is an instance
+-- of the more general genericLength, the result type of which may be
+-- any kind of number.
+length :: [a] -> Int
+length l = len l 0#
+ where
+ len :: [a] -> Int# -> Int
+ len [] a# = I# a#
+ len (_:xs) a# = len xs (a# +# 1#)
+
+-- filter, applied to a predicate and a list, returns the list of those
+-- elements that satisfy the predicate; i.e.,
+-- filter p xs = [ x | x <- xs, p x]
+filter :: (a -> Bool) -> [a] -> [a]
+filter = filterList
+
+filterFB c p x r | p x = x `c` r
+ | otherwise = r
+
+{-# RULES
+"filter" forall p xs. filter p xs = build (\c n -> foldr (filterFB c p) n xs)
+"filterFB" forall c p q. filterFB (filterFB c p) q = filterFB c (\x -> q x && p x)
+"filterList" forall p. foldr (filterFB (:) p) [] = filterList p
+ #-}
+
+-- Note the filterFB rule, which has p and q the "wrong way round" in the RHS.
+-- filterFB (filterFB c p) q a b
+-- = if q a then filterFB c p a b else b
+-- = if q a then (if p a then c a b else b) else b
+-- = if q a && p a then c a b else b
+-- = filterFB c (\x -> q x && p x) a b
+-- I originally wrote (\x -> p x && q x), which is wrong, and actually
+-- gave rise to a live bug report. SLPJ.
+
+filterList :: (a -> Bool) -> [a] -> [a]
+filterList _pred [] = []
+filterList pred (x:xs)
+ | pred x = x : filterList pred xs
+ | otherwise = filterList pred xs
+
+-- foldl, applied to a binary operator, a starting value (typically the
+-- left-identity of the operator), and a list, reduces the list using
+-- the binary operator, from left to right:
+-- foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
+-- foldl1 is a variant that has no starting value argument, and thus must
+-- be applied to non-empty lists. scanl is similar to foldl, but returns
+-- a list of successive reduced values from the left:
+-- scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
+-- Note that last (scanl f z xs) == foldl f z xs.
+-- scanl1 is similar, again without the starting element:
+-- scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
+
+-- We write foldl as a non-recursive thing, so that it
+-- can be inlined, and then (often) strictness-analysed,
+-- and hence the classic space leak on foldl (+) 0 xs
+
+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
+
+foldl1 :: (a -> a -> a) -> [a] -> a
+foldl1 f (x:xs) = foldl f x xs
+foldl1 _ [] = errorEmptyList "foldl1"
+
+scanl :: (a -> b -> a) -> a -> [b] -> [a]
+scanl f q ls = q : (case ls of
+ [] -> []
+ x:xs -> scanl f (f q x) xs)
+
+scanl1 :: (a -> a -> a) -> [a] -> [a]
+scanl1 f (x:xs) = scanl f x xs
+scanl1 _ [] = errorEmptyList "scanl1"
+
+-- foldr, foldr1, scanr, and scanr1 are the right-to-left duals of the
+-- above functions.
+
+foldr1 :: (a -> a -> a) -> [a] -> a
+foldr1 _ [x] = x
+foldr1 f (x:xs) = f x (foldr1 f xs)
+foldr1 _ [] = errorEmptyList "foldr1"
+
+scanr :: (a -> b -> b) -> b -> [a] -> [b]
+scanr _ q0 [] = [q0]
+scanr f q0 (x:xs) = f x q : qs
+ where qs@(q:_) = scanr f q0 xs
+
+scanr1 :: (a -> a -> a) -> [a] -> [a]
+scanr1 _ [x] = [x]
+scanr1 f (x:xs) = f x q : qs
+ where qs@(q:_) = scanr1 f xs
+scanr1 _ [] = errorEmptyList "scanr1"
+
+-- iterate f x returns an infinite list of repeated applications of f to x:
+-- iterate f x == [x, f x, f (f x), ...]
+iterate :: (a -> a) -> a -> [a]
+iterate = iterateList
+
+iterateFB c f x = x `c` iterateFB c f (f x)
+
+iterateList f x = x : iterateList f (f x)
+
+{-# RULES
+"iterate" forall f x. iterate f x = build (\c _n -> iterateFB c f x)
+"iterateFB" iterateFB (:) = iterateList
+ #-}
+
+
+-- repeat x is an infinite list, with x the value of every element.
+repeat :: a -> [a]
+repeat = repeatList
+
+repeatFB c x = xs where xs = x `c` xs
+repeatList x = xs where xs = x : xs
+
+{-# RULES
+"repeat" forall x. repeat x = build (\c _n -> repeatFB c x)
+"repeatFB" repeatFB (:) = repeatList
+ #-}
+
+-- replicate n x is a list of length n with x the value of every element
+replicate :: Int -> a -> [a]
+replicate n x = take n (repeat x)
+
+-- cycle ties a finite list into a circular one, or equivalently,
+-- the infinite repetition of the original list. It is the identity
+-- on infinite lists.
+
+cycle :: [a] -> [a]
+cycle [] = error "Prelude.cycle: empty list"
+cycle xs = xs' where xs' = xs ++ xs'
+
+-- takeWhile, applied to a predicate p and a list xs, returns the longest
+-- prefix (possibly empty) of xs of elements that satisfy p. dropWhile p xs
+-- returns the remaining suffix. Span p xs is equivalent to
+-- (takeWhile p xs, dropWhile p xs), while break p uses the negation of p.
+
+takeWhile :: (a -> Bool) -> [a] -> [a]
+takeWhile _ [] = []
+takeWhile p (x:xs)
+ | p x = x : takeWhile p xs
+ | otherwise = []
+
+dropWhile :: (a -> Bool) -> [a] -> [a]
+dropWhile _ [] = []
+dropWhile p xs@(x:xs')
+ | p x = dropWhile p xs'
+ | otherwise = xs
+
+-- take n, applied to a list xs, returns the prefix of xs of length n,
+-- or xs itself if n > length xs. drop n xs returns the suffix of xs
+-- after the first n elements, or [] if n > length xs. splitAt n xs
+-- is equivalent to (take n xs, drop n xs).
+#ifdef USE_REPORT_PRELUDE
+take :: Int -> [a] -> [a]
+take 0 _ = []
+take _ [] = []
+take n (x:xs) | n > 0 = x : take (minusInt n 1) xs
+take _ _ = errorNegativeIdx "take"
+
+drop :: Int -> [a] -> [a]
+drop 0 xs = xs
+drop _ [] = []
+drop n (_:xs) | n > 0 = drop (minusInt n 1) xs
+drop _ _ = errorNegativeIdx "drop"
+
+
+splitAt :: Int -> [a] -> ([a],[a])
+splitAt 0 xs = ([],xs)
+splitAt _ [] = ([],[])
+splitAt n (x:xs) | n > 0 = (x:xs',xs'') where (xs',xs'') = splitAt (minusInt n 1) xs
+splitAt _ _ = errorNegativeIdx "splitAt"
+
+#else /* hack away */
+take :: Int -> [b] -> [b]
+take (I# n#) xs = takeUInt n# xs
+
+-- The general code for take, below, checks n <= maxInt
+-- No need to check for maxInt overflow when specialised
+-- at type Int or Int# since the Int must be <= maxInt
+
+takeUInt :: Int# -> [b] -> [b]
+takeUInt n xs
+ | n >=# 0# = take_unsafe_UInt n xs
+ | otherwise = errorNegativeIdx "take"
+
+take_unsafe_UInt :: Int# -> [b] -> [b]
+take_unsafe_UInt 0# _ = []
+take_unsafe_UInt m ls =
+ case ls of
+ [] -> []
+ (x:xs) -> x : take_unsafe_UInt (m -# 1#) xs
+
+takeUInt_append :: Int# -> [b] -> [b] -> [b]
+takeUInt_append n xs rs
+ | n >=# 0# = take_unsafe_UInt_append n xs rs
+ | otherwise = errorNegativeIdx "take"
+
+take_unsafe_UInt_append :: Int# -> [b] -> [b] -> [b]
+take_unsafe_UInt_append 0# _ rs = rs
+take_unsafe_UInt_append m ls rs =
+ case ls of
+ [] -> rs
+ (x:xs) -> x : take_unsafe_UInt_append (m -# 1#) xs rs
+
+drop :: Int -> [b] -> [b]
+drop (I# n#) ls
+ | n# <# 0# = errorNegativeIdx "drop"
+ | otherwise = drop# n# ls
+ where
+ drop# :: Int# -> [a] -> [a]
+ drop# 0# xs = xs
+ drop# _ xs@[] = xs
+ drop# m# (_:xs) = drop# (m# -# 1#) xs
+
+splitAt :: Int -> [b] -> ([b], [b])
+splitAt (I# n#) ls
+ | n# <# 0# = errorNegativeIdx "splitAt"
+ | otherwise = splitAt# n# ls
+ where
+ splitAt# :: Int# -> [a] -> ([a], [a])
+ splitAt# 0# xs = ([], xs)
+ splitAt# _ xs@[] = (xs, xs)
+ splitAt# m# (x:xs) = (x:xs', xs'')
+ where
+ (xs', xs'') = splitAt# (m# -# 1#) xs
+
+#endif /* USE_REPORT_PRELUDE */
+
+span, break :: (a -> Bool) -> [a] -> ([a],[a])
+span _ xs@[] = (xs, xs)
+span p xs@(x:xs')
+ | p x = let (ys,zs) = span p xs' in (x:ys,zs)
+ | otherwise = ([],xs)
+
+#ifdef USE_REPORT_PRELUDE
+break p = span (not . p)
+#else
+-- HBC version (stolen)
+break _ xs@[] = (xs, xs)
+break p xs@(x:xs')
+ | p x = ([],xs)
+ | otherwise = let (ys,zs) = break p xs' in (x:ys,zs)
+#endif
+
+-- reverse xs returns the elements of xs in reverse order. xs must be finite.
+reverse :: [a] -> [a]
+#ifdef USE_REPORT_PRELUDE
+reverse = foldl (flip (:)) []
+#else
+reverse l = rev l []
+ where
+ rev [] a = a
+ rev (x:xs) a = rev xs (x:a)
+#endif
+
+-- and returns the conjunction of a Boolean list. For the result to be
+-- True, the list must be finite; False, however, results from a False
+-- value at a finite index of a finite or infinite list. or is the
+-- disjunctive dual of and.
+and, or :: [Bool] -> Bool
+#ifdef USE_REPORT_PRELUDE
+and = foldr (&&) True
+or = foldr (||) False
+#else
+and [] = True
+and (x:xs) = x && and xs
+or [] = False
+or (x:xs) = x || or xs
+
+{-# RULES
+"and/build" forall (g::forall b.(Bool->b->b)->b->b) .
+ and (build g) = g (&&) True
+"or/build" forall (g::forall b.(Bool->b->b)->b->b) .
+ or (build g) = g (||) False
+ #-}
+#endif
+
+-- Applied to a predicate and a list, any determines if any element
+-- of the list satisfies the predicate. Similarly, for all.
+any, all :: (a -> Bool) -> [a] -> Bool
+#ifdef USE_REPORT_PRELUDE
+any p = or . map p
+all p = and . map p
+#else
+any _ [] = False
+any p (x:xs) = p x || any p xs
+
+all _ [] = True
+all p (x:xs) = p x && all p xs
+{-# RULES
+"any/build" forall p (g::forall b.(a->b->b)->b->b) .
+ any p (build g) = g ((||) . p) False
+"all/build" forall p (g::forall b.(a->b->b)->b->b) .
+ all p (build g) = g ((&&) . p) True
+ #-}
+#endif
+
+-- elem is the list membership predicate, usually written in infix form,
+-- e.g., x `elem` xs. notElem is the negation.
+elem, notElem :: (Eq a) => a -> [a] -> Bool
+#ifdef USE_REPORT_PRELUDE
+elem x = any (== x)
+notElem x = all (/= x)
+#else
+elem _ [] = False
+elem x (y:ys) = x==y || elem x ys
+
+notElem _ [] = True
+notElem x (y:ys)= x /= y && notElem x ys
+#endif
+
+-- lookup key assocs looks up a key in an association list.
+lookup :: (Eq a) => a -> [(a,b)] -> Maybe b
+lookup _key [] = Nothing
+lookup key ((x,y):xys)
+ | key == x = Just y
+ | otherwise = lookup key xys
+
+
+-- maximum and minimum return the maximum or minimum value from a list,
+-- which must be non-empty, finite, and of an ordered type.
+{-# SPECIALISE maximum :: [Int] -> Int #-}
+{-# SPECIALISE minimum :: [Int] -> Int #-}
+maximum, minimum :: (Ord a) => [a] -> a
+maximum [] = errorEmptyList "maximum"
+maximum xs = foldl1 max xs
+
+minimum [] = errorEmptyList "minimum"
+minimum xs = foldl1 min xs
+
+concatMap :: (a -> [b]) -> [a] -> [b]
+concatMap f = foldr ((++) . f) []
+
+concat :: [[a]] -> [a]
+concat = foldr (++) []
+
+{-# RULES
+ "concat" forall xs. concat xs = build (\c n -> foldr (\x y -> foldr c y x) n xs)
+ #-}
+\end{code}
+
+
+\begin{code}
+-- List index (subscript) operator, 0-origin
+(!!) :: [a] -> Int -> a
+#ifdef USE_REPORT_PRELUDE
+(x:_) !! 0 = x
+(_:xs) !! n | n > 0 = xs !! (minusInt n 1)
+(_:_) !! _ = error "Prelude.(!!): negative index"
+[] !! _ = error "Prelude.(!!): index too large"
+#else
+-- HBC version (stolen), then unboxified
+-- The semantics is not quite the same for error conditions
+-- in the more efficient version.
+--
+xs !! (I# n) | n <# 0# = error "Prelude.(!!): negative index\n"
+ | otherwise = sub xs n
+ where
+ sub :: [a] -> Int# -> a
+ sub [] _ = error "Prelude.(!!): index too large\n"
+ sub (y:ys) n = if n ==# 0#
+ then y
+ else sub ys (n -# 1#)
+#endif
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The zip family}
+%* *
+%*********************************************************
+
+\begin{code}
+foldr2 _k z [] _ys = z
+foldr2 _k z _xs [] = z
+foldr2 k z (x:xs) (y:ys) = k x y (foldr2 k z xs ys)
+
+foldr2_left _k z _x _r [] = z
+foldr2_left k _z x r (y:ys) = k x y (r ys)
+
+foldr2_right _k z _y _r [] = z
+foldr2_right k _z y r (x:xs) = k x y (r xs)
+
+-- foldr2 k z xs ys = foldr (foldr2_left k z) (\_ -> z) xs ys
+-- foldr2 k z xs ys = foldr (foldr2_right k z) (\_ -> z) ys xs
+{-# RULES
+"foldr2/left" forall k z ys (g::forall b.(a->b->b)->b->b) .
+ foldr2 k z (build g) ys = g (foldr2_left k z) (\_ -> z) ys
+
+"foldr2/right" forall k z xs (g::forall b.(a->b->b)->b->b) .
+ foldr2 k z xs (build g) = g (foldr2_right k z) (\_ -> z) xs
+ #-}
+\end{code}
+
+The foldr2/right rule isn't exactly right, because it changes
+the strictness of foldr2 (and thereby zip)
+
+E.g. main = print (null (zip nonobviousNil (build undefined)))
+ where nonobviousNil = f 3
+ f n = if n == 0 then [] else f (n-1)
+
+I'm going to leave it though.
+
+
+zip takes two lists and returns a list of corresponding pairs. If one
+input list is short, excess elements of the longer list are discarded.
+zip3 takes three lists and returns a list of triples. Zips for larger
+tuples are in the List module.
+
+\begin{code}
+----------------------------------------------
+zip :: [a] -> [b] -> [(a,b)]
+zip = zipList
+
+zipFB c x y r = (x,y) `c` r
+
+
+zipList :: [a] -> [b] -> [(a,b)]
+zipList (a:as) (b:bs) = (a,b) : zipList as bs
+zipList _ _ = []
+
+{-# RULES
+"zip" forall xs ys. zip xs ys = build (\c n -> foldr2 (zipFB c) n xs ys)
+"zipList" foldr2 (zipFB (:)) [] = zipList
+ #-}
+\end{code}
+
+\begin{code}
+----------------------------------------------
+zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
+-- Specification
+-- zip3 = zipWith3 (,,)
+zip3 (a:as) (b:bs) (c:cs) = (a,b,c) : zip3 as bs cs
+zip3 _ _ _ = []
+\end{code}
+
+
+-- The zipWith family generalises the zip family by zipping with the
+-- function given as the first argument, instead of a tupling function.
+-- For example, zipWith (+) is applied to two lists to produce the list
+-- of corresponding sums.
+
+
+\begin{code}
+----------------------------------------------
+zipWith :: (a->b->c) -> [a]->[b]->[c]
+zipWith = zipWithList
+
+
+zipWithFB c f x y r = (x `f` y) `c` r
+
+zipWithList :: (a->b->c) -> [a] -> [b] -> [c]
+zipWithList f (a:as) (b:bs) = f a b : zipWithList f as bs
+zipWithList _ _ _ = []
+
+{-# RULES
+"zipWith" forall f xs ys. zipWith f xs ys = build (\c n -> foldr2 (zipWithFB c f) n xs ys)
+"zipWithList" forall f. foldr2 (zipWithFB (:) f) [] = zipWithList f
+ #-}
+\end{code}
+
+\begin{code}
+zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
+zipWith3 z (a:as) (b:bs) (c:cs)
+ = z a b c : zipWith3 z as bs cs
+zipWith3 _ _ _ _ = []
+
+-- unzip transforms a list of pairs into a pair of lists.
+unzip :: [(a,b)] -> ([a],[b])
+{-# INLINE unzip #-}
+unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])
+
+unzip3 :: [(a,b,c)] -> ([a],[b],[c])
+{-# INLINE unzip3 #-}
+unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
+ ([],[],[])
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Error code}
+%* *
+%*********************************************************
+
+Common up near identical calls to `error' to reduce the number
+constant strings created when compiled:
+
+\begin{code}
+errorEmptyList :: String -> a
+errorEmptyList fun =
+ error (prel_list_str ++ fun ++ ": empty list")
+
+errorNegativeIdx :: String -> a
+errorNegativeIdx fun =
+ error (prel_list_str ++ fun ++ ": negative index")
+
+prel_list_str :: String
+prel_list_str = "Prelude."
+\end{code}
diff --git a/libraries/base/GHC/Main.lhs b/libraries/base/GHC/Main.lhs
new file mode 100644
index 0000000000..6f05dae14a
--- /dev/null
+++ b/libraries/base/GHC/Main.lhs
@@ -0,0 +1,24 @@
+% ------------------------------------------------------------------------------
+% $Id: Main.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Main]{Module @GHC.Main@}
+
+\begin{code}
+module GHC.Main( mainIO ) where
+
+import {-# SOURCE #-} qualified Main -- for type of "Main.main"
+
+import Prelude
+
+import System.IO
+import GHC.Exception
+import GHC.TopHandler
+
+mainIO :: IO () -- It must be of type (IO t) because that's what
+ -- the RTS expects. GHC doesn't check this, so
+ -- make sure this type signature stays!
+mainIO = catchException Main.main topHandler
+\end{code}
diff --git a/libraries/base/GHC/Maybe.lhs b/libraries/base/GHC/Maybe.lhs
new file mode 100644
index 0000000000..2a8189c82d
--- /dev/null
+++ b/libraries/base/GHC/Maybe.lhs
@@ -0,0 +1,64 @@
+% ------------------------------------------------------------------------------
+% $Id: Maybe.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1992-2000
+%
+
+\section[GHC.Maybe]{Module @GHC.Maybe@}
+
+The @Maybe@ type.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Maybe where
+
+import GHC.Base
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Maybe type}
+%* *
+%*********************************************************
+
+\begin{code}
+data Maybe a = Nothing | Just a deriving (Eq, Ord)
+
+maybe :: b -> (a -> b) -> Maybe a -> b
+maybe n _ Nothing = n
+maybe _ f (Just x) = f x
+
+instance Functor Maybe where
+ fmap _ Nothing = Nothing
+ fmap f (Just a) = Just (f a)
+
+instance Monad Maybe where
+ (Just x) >>= k = k x
+ Nothing >>= _ = Nothing
+
+ (Just _) >> k = k
+ Nothing >> _ = Nothing
+
+ return = Just
+ fail _ = Nothing
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Either type}
+%* *
+%*********************************************************
+
+\begin{code}
+data Either a b = Left a | Right b deriving (Eq, Ord )
+
+either :: (a -> c) -> (b -> c) -> Either a b -> c
+either f _ (Left x) = f x
+either _ g (Right y) = g y
+\end{code}
+
+
+
+
diff --git a/libraries/base/GHC/Num.hi-boot b/libraries/base/GHC/Num.hi-boot
new file mode 100644
index 0000000000..33298fdbd7
--- /dev/null
+++ b/libraries/base/GHC/Num.hi-boot
@@ -0,0 +1,14 @@
+---------------------------------------------------------------------------
+-- PrelNum.hi-boot
+--
+-- This hand-written interface file is the
+-- initial bootstrap version for PrelNum.hi.
+-- It's needed for the 'thin-air' Id addr2Integer, when compiling
+-- PrelBase, and other Prelude files that precede PrelNum
+---------------------------------------------------------------------------
+
+__interface "std" PrelNum 1 where
+__export PrelNum Integer addr2Integer ;
+
+1 data Integer ;
+1 addr2Integer :: PrelGHC.Addrzh -> Integer ;
diff --git a/libraries/base/GHC/Num.lhs b/libraries/base/GHC/Num.lhs
new file mode 100644
index 0000000000..c835531488
--- /dev/null
+++ b/libraries/base/GHC/Num.lhs
@@ -0,0 +1,447 @@
+% ------------------------------------------------------------------------------
+% $Id: Num.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Num]{Module @GHC.Num@}
+
+The class
+
+ Num
+
+and the type
+
+ Integer
+
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Num where
+
+import {-# SOURCE #-} GHC.Err
+import GHC.Base
+import GHC.List
+import GHC.Enum
+import GHC.Show
+
+infixl 7 *
+infixl 6 +, -
+
+default () -- Double isn't available yet,
+ -- and we shouldn't be using defaults anyway
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Standard numeric class}
+%* *
+%*********************************************************
+
+\begin{code}
+class (Eq a, Show a) => Num a where
+ (+), (-), (*) :: a -> a -> a
+ negate :: a -> a
+ abs, signum :: a -> a
+ fromInteger :: Integer -> a
+
+ x - y = x + negate y
+ negate x = 0 - x
+
+{-# INLINE subtract #-}
+subtract :: (Num a) => a -> a -> a
+subtract x y = y - x
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Instances for @Int@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Num Int where
+ (+) = plusInt
+ (-) = minusInt
+ negate = negateInt
+ (*) = timesInt
+ abs n = if n `geInt` 0 then n else negateInt n
+
+ signum n | n `ltInt` 0 = negateInt 1
+ | n `eqInt` 0 = 0
+ | otherwise = 1
+
+ fromInteger = integer2Int
+\end{code}
+
+
+\begin{code}
+-- These can't go in GHC.Base with the defn of Int, because
+-- we don't have pairs defined at that time!
+
+quotRemInt :: Int -> Int -> (Int, Int)
+a@(I# _) `quotRemInt` b@(I# _) = (a `quotInt` b, a `remInt` b)
+ -- OK, so I made it a little stricter. Shoot me. (WDP 94/10)
+
+divModInt :: Int -> Int -> (Int, Int)
+divModInt x@(I# _) y@(I# _) = (x `divInt` y, x `modInt` y)
+ -- Stricter. Sorry if you don't like it. (WDP 94/10)
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @Integer@ type}
+%* *
+%*********************************************************
+
+\begin{code}
+data Integer
+ = S# Int# -- small integers
+ | J# Int# ByteArray# -- large integers
+\end{code}
+
+Convenient boxed Integer PrimOps.
+
+\begin{code}
+zeroInteger :: Integer
+zeroInteger = S# 0#
+
+int2Integer :: Int -> Integer
+{-# INLINE int2Integer #-}
+int2Integer (I# i) = S# i
+
+integer2Int :: Integer -> Int
+integer2Int (S# i) = I# i
+integer2Int (J# s d) = case (integer2Int# s d) of { n# -> I# n# }
+
+toBig (S# i) = case int2Integer# i of { (# s, d #) -> J# s d }
+toBig i@(J# _ _) = i
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Dividing @Integers@}
+%* *
+%*********************************************************
+
+\begin{code}
+quotRemInteger :: Integer -> Integer -> (Integer, Integer)
+quotRemInteger a@(S# (-2147483648#)) b = quotRemInteger (toBig a) b
+quotRemInteger (S# i) (S# j)
+ = case quotRemInt (I# i) (I# j) of ( I# i, I# j ) -> ( S# i, S# j )
+quotRemInteger i1@(J# _ _) i2@(S# _) = quotRemInteger i1 (toBig i2)
+quotRemInteger i1@(S# _) i2@(J# _ _) = quotRemInteger (toBig i1) i2
+quotRemInteger (J# s1 d1) (J# s2 d2)
+ = case (quotRemInteger# s1 d1 s2 d2) of
+ (# s3, d3, s4, d4 #)
+ -> (J# s3 d3, J# s4 d4)
+
+divModInteger a@(S# (-2147483648#)) b = divModInteger (toBig a) b
+divModInteger (S# i) (S# j)
+ = case divModInt (I# i) (I# j) of ( I# i, I# j ) -> ( S# i, S# j)
+divModInteger i1@(J# _ _) i2@(S# _) = divModInteger i1 (toBig i2)
+divModInteger i1@(S# _) i2@(J# _ _) = divModInteger (toBig i1) i2
+divModInteger (J# s1 d1) (J# s2 d2)
+ = case (divModInteger# s1 d1 s2 d2) of
+ (# s3, d3, s4, d4 #)
+ -> (J# s3 d3, J# s4 d4)
+
+remInteger :: Integer -> Integer -> Integer
+remInteger ia 0
+ = error "Prelude.Integral.rem{Integer}: divide by 0"
+remInteger a@(S# (-2147483648#)) b = remInteger (toBig a) b
+remInteger (S# a) (S# b) = S# (remInt# a b)
+{- Special case doesn't work, because a 1-element J# has the range
+ -(2^32-1) -- 2^32-1, whereas S# has the range -2^31 -- (2^31-1)
+remInteger ia@(S# a) (J# sb b)
+ | sb ==# 1# = S# (remInt# a (word2Int# (integer2Word# sb b)))
+ | sb ==# -1# = S# (remInt# a (0# -# (word2Int# (integer2Word# sb b))))
+ | 0# <# sb = ia
+ | otherwise = S# (0# -# a)
+-}
+remInteger ia@(S# _) ib@(J# _ _) = remInteger (toBig ia) ib
+remInteger (J# sa a) (S# b)
+ = case int2Integer# b of { (# sb, b #) ->
+ case remInteger# sa a sb b of { (# sr, r #) ->
+ S# (integer2Int# sr r) }}
+remInteger (J# sa a) (J# sb b)
+ = case remInteger# sa a sb b of (# sr, r #) -> J# sr r
+
+quotInteger :: Integer -> Integer -> Integer
+quotInteger ia 0
+ = error "Prelude.Integral.quot{Integer}: divide by 0"
+quotInteger a@(S# (-2147483648#)) b = quotInteger (toBig a) b
+quotInteger (S# a) (S# b) = S# (quotInt# a b)
+{- Special case disabled, see remInteger above
+quotInteger (S# a) (J# sb b)
+ | sb ==# 1# = S# (quotInt# a (word2Int# (integer2Word# sb b)))
+ | sb ==# -1# = S# (quotInt# a (0# -# (word2Int# (integer2Word# sb b))))
+ | otherwise = zeroInteger
+-}
+quotInteger ia@(S# _) ib@(J# _ _) = quotInteger (toBig ia) ib
+quotInteger (J# sa a) (S# b)
+ = case int2Integer# b of { (# sb, b #) ->
+ case quotInteger# sa a sb b of (# sq, q #) -> J# sq q }
+quotInteger (J# sa a) (J# sb b)
+ = case quotInteger# sa a sb b of (# sg, g #) -> J# sg g
+\end{code}
+
+
+
+\begin{code}
+gcdInteger :: Integer -> Integer -> Integer
+-- SUP: Do we really need the first two cases?
+gcdInteger a@(S# (-2147483648#)) b = gcdInteger (toBig a) b
+gcdInteger a b@(S# (-2147483648#)) = gcdInteger a (toBig b)
+gcdInteger (S# a) (S# b) = case gcdInt (I# a) (I# b) of { I# c -> S# c }
+gcdInteger ia@(S# 0#) ib@(J# 0# _) = error "GHC.Num.gcdInteger: gcd 0 0 is undefined"
+gcdInteger ia@(S# a) ib@(J# sb b)
+ | a ==# 0# = abs ib
+ | sb ==# 0# = abs ia
+ | otherwise = S# (gcdIntegerInt# absSb b absA)
+ where absA = if a <# 0# then negateInt# a else a
+ absSb = if sb <# 0# then negateInt# sb else sb
+gcdInteger ia@(J# _ _) ib@(S# _) = gcdInteger ib ia
+gcdInteger (J# 0# _) (J# 0# _) = error "GHC.Num.gcdInteger: gcd 0 0 is undefined"
+gcdInteger (J# sa a) (J# sb b)
+ = case gcdInteger# sa a sb b of (# sg, g #) -> J# sg g
+
+lcmInteger :: Integer -> Integer -> Integer
+lcmInteger a 0
+ = zeroInteger
+lcmInteger 0 b
+ = zeroInteger
+lcmInteger a b
+ = (divExact aa (gcdInteger aa ab)) * ab
+ where aa = abs a
+ ab = abs b
+
+divExact :: Integer -> Integer -> Integer
+divExact a@(S# (-2147483648#)) b = divExact (toBig a) b
+divExact (S# a) (S# b) = S# (quotInt# a b)
+divExact (S# a) (J# sb b)
+ = S# (quotInt# a (integer2Int# sb b))
+divExact (J# sa a) (S# b)
+ = case int2Integer# b of
+ (# sb, b #) -> case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d
+divExact (J# sa a) (J# sb b)
+ = case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @Integer@ instances for @Eq@, @Ord@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Eq Integer where
+ (S# i) == (S# j) = i ==# j
+ (S# i) == (J# s d) = cmpIntegerInt# s d i ==# 0#
+ (J# s d) == (S# i) = cmpIntegerInt# s d i ==# 0#
+ (J# s1 d1) == (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ==# 0#
+
+ (S# i) /= (S# j) = i /=# j
+ (S# i) /= (J# s d) = cmpIntegerInt# s d i /=# 0#
+ (J# s d) /= (S# i) = cmpIntegerInt# s d i /=# 0#
+ (J# s1 d1) /= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) /=# 0#
+
+------------------------------------------------------------------------
+instance Ord Integer where
+ (S# i) <= (S# j) = i <=# j
+ (J# s d) <= (S# i) = cmpIntegerInt# s d i <=# 0#
+ (S# i) <= (J# s d) = cmpIntegerInt# s d i >=# 0#
+ (J# s1 d1) <= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <=# 0#
+
+ (S# i) > (S# j) = i ># j
+ (J# s d) > (S# i) = cmpIntegerInt# s d i ># 0#
+ (S# i) > (J# s d) = cmpIntegerInt# s d i <# 0#
+ (J# s1 d1) > (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ># 0#
+
+ (S# i) < (S# j) = i <# j
+ (J# s d) < (S# i) = cmpIntegerInt# s d i <# 0#
+ (S# i) < (J# s d) = cmpIntegerInt# s d i ># 0#
+ (J# s1 d1) < (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <# 0#
+
+ (S# i) >= (S# j) = i >=# j
+ (J# s d) >= (S# i) = cmpIntegerInt# s d i >=# 0#
+ (S# i) >= (J# s d) = cmpIntegerInt# s d i <=# 0#
+ (J# s1 d1) >= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) >=# 0#
+
+ compare (S# i) (S# j)
+ | i ==# j = EQ
+ | i <=# j = LT
+ | otherwise = GT
+ compare (J# s d) (S# i)
+ = case cmpIntegerInt# s d i of { res# ->
+ if res# <# 0# then LT else
+ if res# ># 0# then GT else EQ
+ }
+ compare (S# i) (J# s d)
+ = case cmpIntegerInt# s d i of { res# ->
+ if res# ># 0# then LT else
+ if res# <# 0# then GT else EQ
+ }
+ compare (J# s1 d1) (J# s2 d2)
+ = case cmpInteger# s1 d1 s2 d2 of { res# ->
+ if res# <# 0# then LT else
+ if res# ># 0# then GT else EQ
+ }
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @Integer@ instances for @Num@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Num Integer where
+ (+) = plusInteger
+ (-) = minusInteger
+ (*) = timesInteger
+ negate = negateInteger
+ fromInteger x = x
+
+ -- ORIG: abs n = if n >= 0 then n else -n
+ abs (S# (-2147483648#)) = 2147483648
+ abs (S# i) = case abs (I# i) of I# j -> S# j
+ abs n@(J# s d) = if (s >=# 0#) then n else J# (negateInt# s) d
+
+ signum (S# i) = case signum (I# i) of I# j -> S# j
+ signum (J# s d)
+ = let
+ cmp = cmpIntegerInt# s d 0#
+ in
+ if cmp ># 0# then S# 1#
+ else if cmp ==# 0# then S# 0#
+ else S# (negateInt# 1#)
+
+plusInteger i1@(S# i) i2@(S# j) = case addIntC# i j of { (# r, c #) ->
+ if c ==# 0# then S# r
+ else toBig i1 + toBig i2 }
+plusInteger i1@(J# _ _) i2@(S# _) = i1 + toBig i2
+plusInteger i1@(S# _) i2@(J# _ _) = toBig i1 + i2
+plusInteger (J# s1 d1) (J# s2 d2) = case plusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
+
+minusInteger i1@(S# i) i2@(S# j) = case subIntC# i j of { (# r, c #) ->
+ if c ==# 0# then S# r
+ else toBig i1 - toBig i2 }
+minusInteger i1@(J# _ _) i2@(S# _) = i1 - toBig i2
+minusInteger i1@(S# _) i2@(J# _ _) = toBig i1 - i2
+minusInteger (J# s1 d1) (J# s2 d2) = case minusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
+
+timesInteger i1@(S# i) i2@(S# j) = case mulIntC# i j of { (# r, c #) ->
+ if c ==# 0# then S# r
+ else toBig i1 * toBig i2 }
+timesInteger i1@(J# _ _) i2@(S# _) = i1 * toBig i2
+timesInteger i1@(S# _) i2@(J# _ _) = toBig i1 * i2
+timesInteger (J# s1 d1) (J# s2 d2) = case timesInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
+
+negateInteger (S# (-2147483648#)) = 2147483648
+negateInteger (S# i) = S# (negateInt# i)
+negateInteger (J# s d) = J# (negateInt# s) d
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @Integer@ instance for @Enum@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Enum Integer where
+ succ x = x + 1
+ pred x = x - 1
+ toEnum n = int2Integer n
+ fromEnum n = integer2Int n
+
+ {-# INLINE enumFrom #-}
+ {-# INLINE enumFromThen #-}
+ {-# INLINE enumFromTo #-}
+ {-# INLINE enumFromThenTo #-}
+ enumFrom x = efdInteger x 1
+ enumFromThen x y = efdInteger x (y-x)
+ enumFromTo x lim = efdtInteger x 1 lim
+ enumFromThenTo x y lim = efdtInteger x (y-x) lim
+
+
+efdInteger = enumDeltaIntegerList
+efdtInteger = enumDeltaToIntegerList
+
+{-# RULES
+"efdInteger" forall x y. efdInteger x y = build (\c _ -> enumDeltaIntegerFB c x y)
+"efdtInteger" forall x y l.efdtInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l)
+"enumDeltaInteger" enumDeltaIntegerFB (:) = enumDeltaIntegerList
+"enumDeltaToInteger" enumDeltaToIntegerFB (:) [] = enumDeltaToIntegerList
+ #-}
+
+enumDeltaIntegerFB :: (Integer -> b -> b) -> Integer -> Integer -> b
+enumDeltaIntegerFB c x d = x `c` enumDeltaIntegerFB c (x+d) d
+
+enumDeltaIntegerList :: Integer -> Integer -> [Integer]
+enumDeltaIntegerList x d = x : enumDeltaIntegerList (x+d) d
+
+enumDeltaToIntegerFB c n x delta lim
+ | delta >= 0 = up_fb c n x delta lim
+ | otherwise = dn_fb c n x delta lim
+
+enumDeltaToIntegerList x delta lim
+ | delta >= 0 = up_list x delta lim
+ | otherwise = dn_list x delta lim
+
+up_fb c n x delta lim = go (x::Integer)
+ where
+ go x | x > lim = n
+ | otherwise = x `c` go (x+delta)
+dn_fb c n x delta lim = go (x::Integer)
+ where
+ go x | x < lim = n
+ | otherwise = x `c` go (x+delta)
+
+up_list x delta lim = go (x::Integer)
+ where
+ go x | x > lim = []
+ | otherwise = x : go (x+delta)
+dn_list x delta lim = go (x::Integer)
+ where
+ go x | x < lim = []
+ | otherwise = x : go (x+delta)
+
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @Integer@ instances for @Show@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Show Integer where
+ showsPrec p n r
+ | n < 0 && p > 6 = '(' : jtos n (')' : r)
+ | otherwise = jtos n r
+ showList = showList__ (showsPrec 0)
+
+jtos :: Integer -> String -> String
+jtos n cs
+ | n < 0 = '-' : jtos' (-n) cs
+ | otherwise = jtos' n cs
+ where
+ jtos' :: Integer -> String -> String
+ jtos' n' cs'
+ | n' < 10 = case unsafeChr (ord '0' + fromInteger n') of
+ c@(C# _) -> c:cs'
+ | otherwise = case unsafeChr (ord '0' + fromInteger r) of
+ c@(C# _) -> jtos' q (c:cs')
+ where
+ (q,r) = n' `quotRemInteger` 10
+\end{code}
diff --git a/libraries/base/GHC/Pack.lhs b/libraries/base/GHC/Pack.lhs
new file mode 100644
index 0000000000..1b4e56ab42
--- /dev/null
+++ b/libraries/base/GHC/Pack.lhs
@@ -0,0 +1,231 @@
+% ------------------------------------------------------------------------------
+% $Id: Pack.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1997-2000
+%
+
+\section[GHC.Pack]{Packing/unpacking bytes}
+
+This module provides a small set of low-level functions for packing
+and unpacking a chunk of bytes. Used by code emitted by the compiler
+plus the prelude libraries.
+
+The programmer level view of packed strings is provided by a GHC
+system library PackedString.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Pack
+ (
+ -- (**) - emitted by compiler.
+
+ packCString#, -- :: [Char] -> ByteArray# **
+ packString, -- :: [Char] -> ByteArray Int
+ packStringST, -- :: [Char] -> ST s (ByteArray Int)
+ packNBytesST, -- :: Int -> [Char] -> ST s (ByteArray Int)
+
+ unpackCString, -- :: Ptr a -> [Char]
+ unpackCStringST, -- :: Ptr a -> ST s [Char]
+ unpackNBytes, -- :: Ptr a -> Int -> [Char]
+ unpackNBytesST, -- :: Ptr a -> Int -> ST s [Char]
+ unpackNBytesAccST, -- :: Ptr a -> Int -> [Char] -> ST s [Char]
+ unpackNBytesAccST#,-- :: Ptr a -> Int -> [Char] -> ST s [Char]
+ unpackCString#, -- :: Addr# -> [Char] **
+ unpackNBytes#, -- :: Addr# -> Int# -> [Char] **
+ unpackNBytesST#, -- :: Addr# -> Int# -> ST s [Char]
+
+ unpackCStringBA, -- :: ByteArray Int -> [Char]
+ unpackNBytesBA, -- :: ByteArray Int -> Int -> [Char]
+ unpackCStringBA#, -- :: ByteArray# -> Int# -> [Char]
+ unpackNBytesBA#, -- :: ByteArray# -> Int# -> [Char]
+
+
+ unpackFoldrCString#, -- **
+ unpackAppendCString#, -- **
+
+ new_ps_array, -- Int# -> ST s (MutableByteArray s Int)
+ write_ps_array, -- MutableByteArray s Int -> Int# -> Char# -> ST s ()
+ freeze_ps_array -- MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
+
+ )
+ where
+
+import GHC.Base
+import {-# SOURCE #-} GHC.Err ( error )
+import GHC.List ( length )
+import GHC.ST
+import GHC.Num
+import GHC.ByteArr
+import Foreign.Ptr
+
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Unpacking Ptrs}
+%* *
+%*********************************************************
+
+Primitives for converting Addrs pointing to external
+sequence of bytes into a list of @Char@s:
+
+\begin{code}
+unpackCString :: Ptr a -> [Char]
+unpackCString a@(Ptr addr)
+ | a == nullPtr = []
+ | otherwise = unpackCString# addr
+
+unpackNBytes :: Ptr a -> Int -> [Char]
+unpackNBytes (Ptr addr) (I# l) = unpackNBytes# addr l
+
+unpackCStringST :: Ptr a{- ptr. to NUL terminated string-} -> ST s [Char]
+unpackCStringST a@(Ptr addr)
+ | a == nullPtr = return []
+ | otherwise = unpack 0#
+ where
+ unpack nh
+ | ch `eqChar#` '\0'# = return []
+ | otherwise = do
+ ls <- unpack (nh +# 1#)
+ return ((C# ch ) : ls)
+ where
+ ch = indexCharOffAddr# addr nh
+
+unpackNBytesST :: Ptr a -> Int -> ST s [Char]
+unpackNBytesST (Ptr addr) (I# l) = unpackNBytesAccST# addr l []
+
+unpackNBytesAccST :: Ptr a -> Int -> [Char] -> ST s [Char]
+unpackNBytesAccST (Ptr addr) (I# l) rest = unpackNBytesAccST# addr l rest
+
+unpackNBytesST# :: Addr# -> Int# -> ST s [Char]
+unpackNBytesST# addr# l# = unpackNBytesAccST# addr# l# []
+
+unpackNBytesAccST# :: Addr# -> Int# -> [Char] -> ST s [Char]
+unpackNBytesAccST# _addr 0# rest = return rest
+unpackNBytesAccST# addr len# rest = unpack rest (len# -# 1#)
+ where
+ unpack acc i#
+ | i# <# 0# = return acc
+ | otherwise =
+ case indexCharOffAddr# addr i# of
+ ch -> unpack (C# ch : acc) (i# -# 1#)
+
+\end{code}
+
+%********************************************************
+%* *
+\subsection{Unpacking ByteArrays}
+%* *
+%********************************************************
+
+Converting byte arrays into list of chars:
+
+\begin{code}
+unpackCStringBA :: ByteArray Int -> [Char]
+unpackCStringBA (ByteArray l@(I# l#) u@(I# u#) bytes)
+ | l > u = []
+ | otherwise = unpackCStringBA# bytes (u# -# l# +# 1#)
+
+{-
+ unpack until NUL or end of BA is reached, whatever comes first.
+-}
+unpackCStringBA# :: ByteArray# -> Int# -> [Char]
+unpackCStringBA# bytes len
+ = unpack 0#
+ where
+ unpack nh
+ | nh >=# len ||
+ ch `eqChar#` '\0'# = []
+ | otherwise = C# ch : unpack (nh +# 1#)
+ where
+ ch = indexCharArray# bytes nh
+
+unpackNBytesBA :: ByteArray Int -> Int -> [Char]
+unpackNBytesBA (ByteArray l u bytes) i
+ = unpackNBytesBA# bytes len#
+ where
+ len# = case max 0 (min i len) of I# v# -> v#
+ len | l > u = 0
+ | otherwise = u-l+1
+
+unpackNBytesBA# :: ByteArray# -> Int# -> [Char]
+unpackNBytesBA# _bytes 0# = []
+unpackNBytesBA# bytes len# = unpack [] (len# -# 1#)
+ where
+ unpack acc i#
+ | i# <# 0# = acc
+ | otherwise =
+ case indexCharArray# bytes i# of
+ ch -> unpack (C# ch : acc) (i# -# 1#)
+
+\end{code}
+
+
+%********************************************************
+%* *
+\subsection{Packing Strings}
+%* *
+%********************************************************
+
+Converting a list of chars into a packed @ByteArray@ representation.
+
+\begin{code}
+packCString# :: [Char] -> ByteArray#
+packCString# str = case (packString str) of { ByteArray _ _ bytes -> bytes }
+
+packString :: [Char] -> ByteArray Int
+packString str = runST (packStringST str)
+
+packStringST :: [Char] -> ST s (ByteArray Int)
+packStringST str =
+ let len = length str in
+ packNBytesST len str
+
+packNBytesST :: Int -> [Char] -> ST s (ByteArray Int)
+packNBytesST (I# length#) str =
+ {-
+ allocate an array that will hold the string
+ (not forgetting the NUL byte at the end)
+ -}
+ new_ps_array (length# +# 1#) >>= \ ch_array ->
+ -- fill in packed string from "str"
+ fill_in ch_array 0# str >>
+ -- freeze the puppy:
+ freeze_ps_array ch_array length#
+ where
+ fill_in :: MutableByteArray s Int -> Int# -> [Char] -> ST s ()
+ fill_in arr_in# idx [] =
+ write_ps_array arr_in# idx (chr# 0#) >>
+ return ()
+
+ fill_in arr_in# idx (C# c : cs) =
+ write_ps_array arr_in# idx c >>
+ fill_in arr_in# (idx +# 1#) cs
+
+\end{code}
+
+(Very :-) ``Specialised'' versions of some CharArray things...
+
+\begin{code}
+new_ps_array :: Int# -> ST s (MutableByteArray s Int)
+write_ps_array :: MutableByteArray s Int -> Int# -> Char# -> ST s ()
+freeze_ps_array :: MutableByteArray s Int -> Int# -> ST s (ByteArray Int)
+
+new_ps_array size = ST $ \ s ->
+ case (newByteArray# size s) of { (# s2#, barr# #) ->
+ (# s2#, MutableByteArray bot bot barr# #) }
+ where
+ bot = error "new_ps_array"
+
+write_ps_array (MutableByteArray _ _ barr#) n ch = ST $ \ s# ->
+ case writeCharArray# barr# n ch s# of { s2# ->
+ (# s2#, () #) }
+
+-- same as unsafeFreezeByteArray
+freeze_ps_array (MutableByteArray _ _ arr#) len# = ST $ \ s# ->
+ case unsafeFreezeByteArray# arr# s# of { (# s2#, frozen# #) ->
+ (# s2#, ByteArray 0 (I# len#) frozen# #) }
+\end{code}
+
+
diff --git a/libraries/base/GHC/Posix.hsc b/libraries/base/GHC/Posix.hsc
new file mode 100644
index 0000000000..b0adbe44fe
--- /dev/null
+++ b/libraries/base/GHC/Posix.hsc
@@ -0,0 +1,295 @@
+{-# OPTIONS -fno-implicit-prelude -optc-DNON_POSIX_SOURCE #-}
+
+-- ---------------------------------------------------------------------------
+-- $Id: Posix.hsc,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- POSIX support layer for the standard libraries
+--
+-- NON_POSIX_SOURCE needed for the following features:
+-- * S_ISSOCK (no sockets in POSIX)
+
+module GHC.Posix where
+
+#include "HsCore.h"
+
+import Control.Monad
+
+import Foreign
+import Foreign.C
+
+import Data.Bits
+import Data.Maybe
+
+import GHC.Base
+import GHC.Num
+import GHC.Real
+import GHC.IOBase
+
+-- ---------------------------------------------------------------------------
+-- Types
+
+data CDir = CDir
+type CSigset = ()
+
+type CDev = #type dev_t
+type CIno = #type ino_t
+type CMode = #type mode_t
+type COff = #type off_t
+type CPid = #type pid_t
+
+#ifdef mingw32_TARGET_OS
+type CSsize = #type size_t
+#else
+type CGid = #type gid_t
+type CNlink = #type nlink_t
+type CSsize = #type ssize_t
+type CUid = #type uid_t
+type CCc = #type cc_t
+type CSpeed = #type speed_t
+type CTcflag = #type tcflag_t
+#endif
+
+-- ---------------------------------------------------------------------------
+-- stat()-related stuff
+
+type CStat = ()
+
+fdFileSize :: Int -> IO Integer
+fdFileSize fd =
+ allocaBytes (#const sizeof(struct stat)) $ \ p_stat -> do
+ throwErrnoIfMinus1Retry "fdFileSize" $
+ c_fstat (fromIntegral fd) p_stat
+ c_mode <- (#peek struct stat, st_mode) p_stat :: IO CMode
+ if not (s_isreg c_mode)
+ then return (-1)
+ else do
+ c_size <- (#peek struct stat, st_size) p_stat :: IO COff
+ return (fromIntegral c_size)
+
+data FDType = Directory | Stream | RegularFile
+ deriving (Eq)
+
+fileType :: FilePath -> IO FDType
+fileType file =
+ allocaBytes (#const sizeof(struct stat)) $ \ p_stat -> do
+ withCString file $ \p_file -> do
+ throwErrnoIfMinus1Retry "fileType" $
+ c_stat p_file p_stat
+ statGetType p_stat
+
+fdType :: Int -> IO FDType
+fdType fd =
+ allocaBytes (#const sizeof(struct stat)) $ \ p_stat -> do
+ throwErrnoIfMinus1Retry "fdType" $
+ c_fstat (fromIntegral fd) p_stat
+ statGetType p_stat
+
+statGetType p_stat = do
+ c_mode <- (#peek struct stat, st_mode) p_stat :: IO CMode
+ case () of
+ _ | s_isdir c_mode -> return Directory
+ | s_isfifo c_mode || s_issock c_mode -> return Stream
+ | s_isreg c_mode -> return RegularFile
+ | otherwise -> ioException ioe_unknownfiletype
+
+
+ioe_unknownfiletype = IOError Nothing UnsupportedOperation "fdType"
+ "unknown file type" Nothing
+
+foreign import "s_isreg_wrap" s_isreg :: CMode -> Bool
+#def inline int s_isreg_wrap(m) { return S_ISREG(m); }
+
+foreign import "s_isdir_wrap" s_isdir :: CMode -> Bool
+#def inline int s_isdir_wrap(m) { return S_ISDIR(m); }
+
+foreign import "s_isfifo_wrap" s_isfifo :: CMode -> Bool
+#def inline int s_isfifo_wrap(m) { return S_ISFIFO(m); }
+
+#ifndef mingw32_TARGET_OS
+foreign import "s_issock_wrap" s_issock :: CMode -> Bool
+#def inline int s_issock_wrap(m) { return S_ISSOCK(m); }
+#else
+s_issock :: CMode -> Bool
+s_issock cmode = False
+#endif
+-- ---------------------------------------------------------------------------
+-- Terminal-related stuff
+
+fdIsTTY :: Int -> IO Bool
+fdIsTTY fd = c_isatty (fromIntegral fd) >>= return.toBool
+
+#ifndef mingw32_TARGET_OS
+
+type Termios = ()
+
+setEcho :: Int -> Bool -> IO ()
+setEcho fd on = do
+ allocaBytes (#const sizeof(struct termios)) $ \p_tios -> do
+ throwErrnoIfMinus1Retry "setEcho"
+ (c_tcgetattr (fromIntegral fd) p_tios)
+ c_lflag <- (#peek struct termios, c_lflag) p_tios :: IO CTcflag
+ let new_c_lflag | on = c_lflag .|. (#const ECHO)
+ | otherwise = c_lflag .&. complement (#const ECHO)
+ (#poke struct termios, c_lflag) p_tios (new_c_lflag :: CTcflag)
+ tcSetAttr fd (#const TCSANOW) p_tios
+
+getEcho :: Int -> IO Bool
+getEcho fd = do
+ allocaBytes (#const sizeof(struct termios)) $ \p_tios -> do
+ throwErrnoIfMinus1Retry "setEcho"
+ (c_tcgetattr (fromIntegral fd) p_tios)
+ c_lflag <- (#peek struct termios, c_lflag) p_tios :: IO CTcflag
+ return ((c_lflag .&. (#const ECHO)) /= 0)
+
+setCooked :: Int -> Bool -> IO ()
+setCooked fd cooked =
+ allocaBytes (#const sizeof(struct termios)) $ \p_tios -> do
+ throwErrnoIfMinus1Retry "setCooked"
+ (c_tcgetattr (fromIntegral fd) p_tios)
+
+ -- turn on/off ICANON
+ c_lflag <- (#peek struct termios, c_lflag) p_tios :: IO CTcflag
+ let new_c_lflag | cooked = c_lflag .|. (#const ICANON)
+ | otherwise = c_lflag .&. complement (#const ICANON)
+ (#poke struct termios, c_lflag) p_tios (new_c_lflag :: CTcflag)
+
+ -- set VMIN & VTIME to 1/0 respectively
+ when cooked $ do
+ let c_cc = (#ptr struct termios, c_cc) p_tios
+ vmin = c_cc `plusPtr` (#const VMIN) :: Ptr Word8
+ vtime = c_cc `plusPtr` (#const VTIME) :: Ptr Word8
+ poke vmin 1
+ poke vtime 0
+
+ tcSetAttr fd (#const TCSANOW) p_tios
+
+-- tcsetattr() when invoked by a background process causes the process
+-- to be sent SIGTTOU regardless of whether the process has TOSTOP set
+-- in its terminal flags (try it...). This function provides a
+-- wrapper which temporarily blocks SIGTTOU around the call, making it
+-- transparent.
+
+tcSetAttr :: FD -> CInt -> Ptr Termios -> IO ()
+tcSetAttr fd options p_tios = do
+ allocaBytes (#const sizeof(sigset_t)) $ \ p_sigset -> do
+ allocaBytes (#const sizeof(sigset_t)) $ \ p_old_sigset -> do
+ c_sigemptyset p_sigset
+ c_sigaddset p_sigset (#const SIGTTOU)
+ c_sigprocmask (#const SIG_BLOCK) p_sigset p_old_sigset
+ throwErrnoIfMinus1Retry_ "tcSetAttr" $
+ c_tcsetattr (fromIntegral fd) options p_tios
+ c_sigprocmask (#const SIG_SETMASK) p_old_sigset nullPtr
+
+#else
+
+-- bogus defns for win32
+setCooked :: Int -> Bool -> IO ()
+setCooked fd cooked = return ()
+
+setEcho :: Int -> Bool -> IO ()
+setEcho fd on = return ()
+
+getEcho :: Int -> IO Bool
+getEcho fd = return False
+
+#endif
+
+-- ---------------------------------------------------------------------------
+-- Turning on non-blocking for a file descriptor
+
+#ifndef mingw32_TARGET_OS
+
+setNonBlockingFD fd = do
+ flags <- throwErrnoIfMinus1Retry "setNonBlockingFD"
+ (fcntl_read (fromIntegral fd) (#const F_GETFL))
+ throwErrnoIfMinus1Retry "setNonBlockingFD"
+ (fcntl_write (fromIntegral fd)
+ (#const F_SETFL) (flags .|. #const O_NONBLOCK))
+#else
+
+-- bogus defns for win32
+setNonBlockingFD fd = return ()
+
+#endif
+
+-- -----------------------------------------------------------------------------
+-- foreign imports
+
+foreign import "stat" unsafe
+ c_stat :: CString -> Ptr CStat -> IO CInt
+
+foreign import "fstat" unsafe
+ c_fstat :: CInt -> Ptr CStat -> IO CInt
+
+#ifdef HAVE_LSTAT
+foreign import "lstat" unsafe
+ c_lstat :: CString -> Ptr CStat -> IO CInt
+#endif
+
+foreign import "open" unsafe
+ c_open :: CString -> CInt -> CMode -> IO CInt
+
+-- POSIX flags only:
+o_RDONLY = (#const O_RDONLY) :: CInt
+o_WRONLY = (#const O_WRONLY) :: CInt
+o_RDWR = (#const O_RDWR) :: CInt
+o_APPEND = (#const O_APPEND) :: CInt
+o_CREAT = (#const O_CREAT) :: CInt
+o_EXCL = (#const O_EXCL) :: CInt
+o_TRUNC = (#const O_TRUNC) :: CInt
+
+#ifdef mingw32_TARGET_OS
+o_NOCTTY = 0 :: CInt
+o_NONBLOCK = 0 :: CInt
+#else
+o_NOCTTY = (#const O_NOCTTY) :: CInt
+o_NONBLOCK = (#const O_NONBLOCK) :: CInt
+#endif
+
+#ifdef HAVE_O_BINARY
+o_BINARY = (#const O_BINARY) :: CInt
+#endif
+
+foreign import "isatty" unsafe
+ c_isatty :: CInt -> IO CInt
+
+foreign import "close" unsafe
+ c_close :: CInt -> IO CInt
+
+foreign import "lseek" unsafe
+ c_lseek :: CInt -> COff -> CInt -> IO COff
+
+foreign import "write" unsafe
+ c_write :: CInt -> Ptr CChar -> CSize -> IO CSsize
+
+foreign import "read" unsafe
+ c_read :: CInt -> Ptr CChar -> CSize -> IO CSsize
+
+#ifndef mingw32_TARGET_OS
+foreign import "fcntl" unsafe
+ fcntl_read :: CInt -> CInt -> IO CInt
+
+foreign import "fcntl" unsafe
+ fcntl_write :: CInt -> CInt -> CInt -> IO CInt
+
+foreign import "fork" unsafe
+ fork :: IO CPid
+
+foreign import "sigemptyset" unsafe
+ c_sigemptyset :: Ptr CSigset -> IO ()
+
+foreign import "sigaddset" unsafe
+ c_sigaddset :: Ptr CSigset -> CInt -> IO ()
+
+foreign import "sigprocmask" unsafe
+ c_sigprocmask :: CInt -> Ptr CSigset -> Ptr CSigset -> IO ()
+
+foreign import "tcgetattr" unsafe
+ c_tcgetattr :: CInt -> Ptr Termios -> IO CInt
+
+foreign import "tcsetattr" unsafe
+ c_tcsetattr :: CInt -> CInt -> Ptr Termios -> IO CInt
+
+foreign import "waitpid" unsafe
+ c_waitpid :: CPid -> Ptr CInt -> CInt -> IO CPid
+#endif
diff --git a/libraries/base/GHC/Prim.hi-boot b/libraries/base/GHC/Prim.hi-boot
new file mode 100644
index 0000000000..9028566698
--- /dev/null
+++ b/libraries/base/GHC/Prim.hi-boot
@@ -0,0 +1,441 @@
+---------------------------------------------------------------------------
+-- PrelGHC.hi-boot
+--
+-- This hand-written interface file allows you to bring into scope the
+-- primitive operations and types that GHC knows about.
+---------------------------------------------------------------------------
+
+__interface "rts" GHCziPrim 1 0 where
+
+__export GHCziPrim
+
+ ZLzmzgZR -- (->)
+
+ CCallable
+ CReturnable
+
+-- Magical assert thingy
+ assert
+
+ -- constructor tags
+ tagToEnumzh
+ getTagzh
+ dataToTagzh
+
+ -- I/O primitives
+ RealWorld
+ realWorldzh
+ Statezh
+
+ -- Concurrency primitives
+ ThreadIdzh
+ myThreadIdzh
+ forkzh
+ yieldzh
+ killThreadzh
+ blockAsyncExceptionszh
+ unblockAsyncExceptionszh
+ delayzh
+ waitReadzh
+ waitWritezh
+
+ -- MVars
+ MVarzh
+ sameMVarzh
+ newMVarzh
+ takeMVarzh
+ putMVarzh
+ tryTakeMVarzh
+ tryPutMVarzh
+ isEmptyMVarzh
+
+ -- Parallel
+ seqzh
+ parzh
+ parGlobalzh
+ parLocalzh
+ parAtzh
+ parAtAbszh
+ parAtRelzh
+ parAtForNowzh
+
+ -- Character Type
+ Charzh
+ gtCharzh
+ geCharzh
+ eqCharzh
+ neCharzh
+ ltCharzh
+ leCharzh
+ ordzh
+ chrzh
+
+ -- Int Type
+ Intzh
+ zgzh
+ zgzezh
+ zezezh
+ zszezh
+ zlzh
+ zlzezh
+ zpzh
+ zmzh
+ ztzh
+ quotIntzh
+ remIntzh
+ gcdIntzh
+ negateIntzh
+ iShiftLzh
+ iShiftRAzh
+ iShiftRLzh
+ addIntCzh
+ subIntCzh
+ mulIntCzh
+
+ Wordzh
+ gtWordzh
+ geWordzh
+ eqWordzh
+ neWordzh
+ ltWordzh
+ leWordzh
+ plusWordzh
+ minusWordzh
+ timesWordzh
+ quotWordzh
+ remWordzh
+ andzh
+ orzh
+ notzh
+ xorzh
+ shiftLzh
+ shiftRLzh
+ int2Wordzh
+ word2Intzh
+
+ Int64zh
+ Word64zh
+
+ intToInt8zh
+ intToInt16zh
+ intToInt32zh
+ wordToWord8zh
+ wordToWord16zh
+ wordToWord32zh
+
+ Addrzh
+ gtAddrzh
+ geAddrzh
+ eqAddrzh
+ neAddrzh
+ ltAddrzh
+ leAddrzh
+ int2Addrzh
+ addr2Intzh
+
+ Floatzh
+ gtFloatzh
+ geFloatzh
+ eqFloatzh
+ neFloatzh
+ ltFloatzh
+ leFloatzh
+ plusFloatzh
+ minusFloatzh
+ timesFloatzh
+ divideFloatzh
+ negateFloatzh
+ float2Intzh
+ int2Floatzh
+ expFloatzh
+ logFloatzh
+ sqrtFloatzh
+ sinFloatzh
+ cosFloatzh
+ tanFloatzh
+ asinFloatzh
+ acosFloatzh
+ atanFloatzh
+ sinhFloatzh
+ coshFloatzh
+ tanhFloatzh
+ powerFloatzh
+ decodeFloatzh
+
+ Doublezh
+ zgzhzh
+ zgzezhzh
+ zezezhzh
+ zszezhzh
+ zlzhzh
+ zlzezhzh
+ zpzhzh
+ zmzhzh
+ ztzhzh
+ zszhzh
+ negateDoublezh
+ double2Intzh
+ int2Doublezh
+ double2Floatzh
+ float2Doublezh
+ expDoublezh
+ logDoublezh
+ sqrtDoublezh
+ sinDoublezh
+ cosDoublezh
+ tanDoublezh
+ asinDoublezh
+ acosDoublezh
+ atanDoublezh
+ sinhDoublezh
+ coshDoublezh
+ tanhDoublezh
+ ztztzhzh
+ decodeDoublezh
+
+ cmpIntegerzh
+ cmpIntegerIntzh
+ plusIntegerzh
+ minusIntegerzh
+ timesIntegerzh
+ gcdIntegerzh
+ quotIntegerzh
+ remIntegerzh
+ gcdIntegerzh
+ gcdIntegerIntzh
+ divExactIntegerzh
+ quotRemIntegerzh
+ divModIntegerzh
+ integer2Intzh
+ integer2Wordzh
+ int2Integerzh
+ word2Integerzh
+ integerToInt64zh
+ integerToWord64zh
+ int64ToIntegerzh
+ word64ToIntegerzh
+ andIntegerzh
+ orIntegerzh
+ xorIntegerzh
+ complementIntegerzh
+
+ Arrayzh
+ ByteArrayzh
+ MutableArrayzh
+ MutableByteArrayzh
+
+ sameMutableArrayzh
+ sameMutableByteArrayzh
+
+ newArrayzh
+ newByteArrayzh
+
+ indexArrayzh
+ indexCharArrayzh
+ indexWideCharArrayzh
+ indexIntArrayzh
+ indexWordArrayzh
+ indexAddrArrayzh
+ indexFloatArrayzh
+ indexDoubleArrayzh
+ indexStablePtrArrayzh
+ indexInt8Arrayzh
+ indexInt16Arrayzh
+ indexInt32Arrayzh
+ indexInt64Arrayzh
+ indexWord8Arrayzh
+ indexWord16Arrayzh
+ indexWord32Arrayzh
+ indexWord64Arrayzh
+
+ readArrayzh
+ readCharArrayzh
+ readWideCharArrayzh
+ readIntArrayzh
+ readWordArrayzh
+ readAddrArrayzh
+ readFloatArrayzh
+ readDoubleArrayzh
+ readStablePtrArrayzh
+ readInt8Arrayzh
+ readInt16Arrayzh
+ readInt32Arrayzh
+ readInt64Arrayzh
+ readWord8Arrayzh
+ readWord16Arrayzh
+ readWord32Arrayzh
+ readWord64Arrayzh
+
+ writeArrayzh
+ writeCharArrayzh
+ writeWideCharArrayzh
+ writeIntArrayzh
+ writeWordArrayzh
+ writeAddrArrayzh
+ writeFloatArrayzh
+ writeDoubleArrayzh
+ writeStablePtrArrayzh
+ writeInt8Arrayzh
+ writeInt16Arrayzh
+ writeInt32Arrayzh
+ writeInt64Arrayzh
+ writeWord8Arrayzh
+ writeWord16Arrayzh
+ writeWord32Arrayzh
+ writeWord64Arrayzh
+
+ indexCharOffAddrzh
+ indexWideCharOffAddrzh
+ indexIntOffAddrzh
+ indexWordOffAddrzh
+ indexAddrOffAddrzh
+ indexFloatOffAddrzh
+ indexDoubleOffAddrzh
+ indexStablePtrOffAddrzh
+ indexInt8OffAddrzh
+ indexInt16OffAddrzh
+ indexInt32OffAddrzh
+ indexInt64OffAddrzh
+ indexWord8OffAddrzh
+ indexWord16OffAddrzh
+ indexWord32OffAddrzh
+ indexWord64OffAddrzh
+
+ readCharOffAddrzh
+ readWideCharOffAddrzh
+ readIntOffAddrzh
+ readWordOffAddrzh
+ readAddrOffAddrzh
+ readFloatOffAddrzh
+ readDoubleOffAddrzh
+ readStablePtrOffAddrzh
+ readInt8OffAddrzh
+ readInt16OffAddrzh
+ readInt32OffAddrzh
+ readInt64OffAddrzh
+ readWord8OffAddrzh
+ readWord16OffAddrzh
+ readWord32OffAddrzh
+ readWord64OffAddrzh
+
+ writeCharOffAddrzh
+ writeWideCharOffAddrzh
+ writeIntOffAddrzh
+ writeWordOffAddrzh
+ writeAddrOffAddrzh
+ writeForeignObjOffAddrzh
+ writeFloatOffAddrzh
+ writeDoubleOffAddrzh
+ writeStablePtrOffAddrzh
+ writeInt8OffAddrzh
+ writeInt16OffAddrzh
+ writeInt32OffAddrzh
+ writeInt64OffAddrzh
+ writeWord8OffAddrzh
+ writeWord16OffAddrzh
+ writeWord32OffAddrzh
+ writeWord64OffAddrzh
+
+ indexCharOffForeignObjzh
+ indexWideCharOffForeignObjzh
+ indexIntOffForeignObjzh
+ indexWordOffForeignObjzh
+ indexAddrOffForeignObjzh
+ indexFloatOffForeignObjzh
+ indexDoubleOffForeignObjzh
+ indexStablePtrOffForeignObjzh
+ indexInt8OffForeignObjzh
+ indexInt16OffForeignObjzh
+ indexInt32OffForeignObjzh
+ indexInt64OffForeignObjzh
+ indexWord8OffForeignObjzh
+ indexWord16OffForeignObjzh
+ indexWord32OffForeignObjzh
+ indexWord64OffForeignObjzh
+
+ unsafeFreezzeArrayzh -- Note zz in the middle
+ unsafeFreezzeByteArrayzh -- Ditto
+
+ unsafeThawArrayzh
+
+ sizzeofByteArrayzh -- Ditto
+ sizzeofMutableByteArrayzh -- Ditto
+
+ MutVarzh
+ newMutVarzh
+ readMutVarzh
+ writeMutVarzh
+ sameMutVarzh
+
+ catchzh
+ raisezh
+
+ Weakzh
+ mkWeakzh
+ deRefWeakzh
+ finalizzeWeakzh
+
+ ForeignObjzh
+ mkForeignObjzh
+ writeForeignObjzh
+ foreignObjToAddrzh
+ touchzh
+
+ StablePtrzh
+ makeStablePtrzh
+ deRefStablePtrzh
+ eqStablePtrzh
+
+ StableNamezh
+ makeStableNamezh
+ eqStableNamezh
+ stableNameToIntzh
+
+ reallyUnsafePtrEqualityzh
+
+ newBCOzh
+ BCOzh
+ mkApUpd0zh
+
+ unsafeCoercezh
+ addrToHValuezh
+;
+
+-- Export GHC.Err.error, so that others don't have to import PrelErr
+__export GHCziErr error ;
+
+
+--------------------------------------------------
+instance {CCallable Charzh} = zdfCCallableCharzh;
+instance {CCallable Doublezh} = zdfCCallableDoublezh;
+instance {CCallable Floatzh} = zdfCCallableFloatzh;
+instance {CCallable Intzh} = zdfCCallableIntzh;
+instance {CCallable Addrzh} = zdfCCallableAddrzh;
+instance {CCallable Int64zh} = zdfCCallableInt64zh;
+instance {CCallable Word64zh} = zdfCCallableWord64zh;
+instance {CCallable Wordzh} = zdfCCallableWordzh;
+instance {CCallable ByteArrayzh} = zdfCCallableByteArrayzh;
+instance __forall s => {CCallable (MutableByteArrayzh s)} = zdfCCallableMutableByteArrayzh;
+instance {CCallable ForeignObjzh} = zdfCCallableForeignObjzh;
+instance __forall s => {CCallable (StablePtrzh s)} = zdfCCallableStablePtrzh;
+-- CCallable and CReturnable have kind (Type AnyBox) so that
+-- things like Int# can be instances of CCallable.
+1 class CCallable a :: ? ;
+1 class CReturnable a :: ? ;
+
+1 assert :: __forall a => GHCziBase.Bool -> a -> a ;
+
+-- These guys don't really exist:
+--
+1 zdfCCallableCharzh :: {CCallable Charzh} ;
+1 zdfCCallableDoublezh :: {CCallable Doublezh} ;
+1 zdfCCallableFloatzh :: {CCallable Floatzh} ;
+1 zdfCCallableIntzh :: {CCallable Intzh} ;
+1 zdfCCallableAddrzh :: {CCallable Addrzh} ;
+1 zdfCCallableInt64zh :: {CCallable Int64zh} ;
+1 zdfCCallableWord64zh :: {CCallable Word64zh} ;
+1 zdfCCallableWordzh :: {CCallable Wordzh} ;
+1 zdfCCallableByteArrayzh :: {CCallable ByteArrayzh} ;
+1 zdfCCallableMutableByteArrayzh :: __forall s => {CCallable (MutableByteArrayzh s)} ;
+1 zdfCCallableForeignObjzh :: {CCallable ForeignObjzh} ;
+1 zdfCCallableStablePtrzh :: __forall a => {CCallable (StablePtrzh a)} ;
diff --git a/libraries/base/GHC/Ptr.lhs b/libraries/base/GHC/Ptr.lhs
new file mode 100644
index 0000000000..61b7f3e2e0
--- /dev/null
+++ b/libraries/base/GHC/Ptr.lhs
@@ -0,0 +1,61 @@
+-----------------------------------------------------------------------------
+-- $Id: Ptr.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- (c) The FFI Task Force, 2000
+--
+-- Module GHC.Ptr
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+module GHC.Ptr where
+
+import GHC.Base
+
+------------------------------------------------------------------------
+-- Data pointers.
+
+data Ptr a = Ptr Addr# deriving (Eq, Ord)
+
+nullPtr :: Ptr a
+nullPtr = Ptr (int2Addr# 0#)
+
+castPtr :: Ptr a -> Ptr b
+castPtr (Ptr addr) = Ptr addr
+
+plusPtr :: Ptr a -> Int -> Ptr b
+plusPtr (Ptr addr) (I# d) = Ptr (int2Addr# (addr2Int# addr +# d))
+
+alignPtr :: Ptr a -> Int -> Ptr a
+alignPtr addr@(Ptr a) (I# i)
+ = case addr2Int# a of { ai ->
+ case remInt# ai i of {
+ 0# -> addr;
+ n -> Ptr (int2Addr# (ai +# (i -# n))) }}
+
+minusPtr :: Ptr a -> Ptr b -> Int
+minusPtr (Ptr a1) (Ptr a2) = I# (addr2Int# a1 -# addr2Int# a2)
+
+instance CCallable (Ptr a)
+instance CReturnable (Ptr a)
+
+------------------------------------------------------------------------
+-- Function pointers for the default calling convention.
+
+data FunPtr a = FunPtr Addr# deriving (Eq, Ord)
+
+nullFunPtr :: FunPtr a
+nullFunPtr = FunPtr (int2Addr# 0#)
+
+castFunPtr :: FunPtr a -> FunPtr b
+castFunPtr (FunPtr addr) = FunPtr addr
+
+castFunPtrToPtr :: FunPtr a -> Ptr b
+castFunPtrToPtr (FunPtr addr) = Ptr addr
+
+castPtrToFunPtr :: Ptr a -> FunPtr b
+castPtrToFunPtr (Ptr addr) = FunPtr addr
+
+instance CCallable (FunPtr a)
+instance CReturnable (FunPtr a)
+
+\end{code}
diff --git a/libraries/base/GHC/Read.lhs b/libraries/base/GHC/Read.lhs
new file mode 100644
index 0000000000..1e66f85a96
--- /dev/null
+++ b/libraries/base/GHC/Read.lhs
@@ -0,0 +1,608 @@
+% ------------------------------------------------------------------------------
+% $Id: Read.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Read]{Module @GHC.Read@}
+
+Instances of the Read class.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Read where
+
+import {-# SOURCE #-} GHC.Err ( error )
+import GHC.Enum ( Enum(..), maxBound )
+import GHC.Num
+import GHC.Real
+import GHC.Float
+import GHC.List
+import GHC.Maybe
+import GHC.Show -- isAlpha etc
+import GHC.Base
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{The @Read@ class}
+%* *
+%*********************************************************
+
+Note: if you compile this with -DNEW_READS_REP, you'll get
+a (simpler) ReadS representation that only allow one valid
+parse of a string of characters, instead of a list of
+possible ones.
+
+[changing the ReadS rep has implications for the deriving
+machinery for Read, a change that hasn't been made, so you
+probably won't want to compile in this new rep. except
+when in an experimental mood.]
+
+\begin{code}
+
+#ifndef NEW_READS_REP
+type ReadS a = String -> [(a,String)]
+#else
+type ReadS a = String -> Maybe (a,String)
+#endif
+
+class Read a where
+ readsPrec :: Int -> ReadS a
+
+ readList :: ReadS [a]
+ readList = readList__ reads
+\end{code}
+
+In this module we treat [(a,String)] as a monad in Control.MonadPlus
+But Control.MonadPlus isn't defined yet, so we simply give local
+declarations for mzero and guard suitable for this particular
+type. It would also be reasonably to move Control.MonadPlus to GHC.Base
+along with Control.Monad and Functor, but that seems overkill for one
+example
+
+\begin{code}
+mzero :: [a]
+mzero = []
+
+guard :: Bool -> [()]
+guard True = [()]
+guard False = []
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Utility functions}
+%* *
+%*********************************************************
+
+\begin{code}
+reads :: (Read a) => ReadS a
+reads = readsPrec 0
+
+read :: (Read a) => String -> a
+read s =
+ case read_s s of
+#ifndef NEW_READS_REP
+ [x] -> x
+ [] -> error "Prelude.read: no parse"
+ _ -> error "Prelude.read: ambiguous parse"
+#else
+ Just x -> x
+ Nothing -> error "Prelude.read: no parse"
+#endif
+ where
+ read_s str = do
+ (x,str1) <- reads str
+ ("","") <- lex str1
+ return x
+\end{code}
+
+\begin{code}
+readParen :: Bool -> ReadS a -> ReadS a
+readParen b g = if b then mandatory else optional
+ where optional r = g r ++ mandatory r
+ mandatory r = do
+ ("(",s) <- lex r
+ (x,t) <- optional s
+ (")",u) <- lex t
+ return (x,u)
+
+
+readList__ :: ReadS a -> ReadS [a]
+
+readList__ readx
+ = readParen False (\r -> do
+ ("[",s) <- lex r
+ readl s)
+ where readl s =
+ (do { ("]",t) <- lex s ; return ([],t) }) ++
+ (do { (x,t) <- readx s ; (xs,u) <- readl2 t ; return (x:xs,u) })
+
+ readl2 s =
+ (do { ("]",t) <- lex s ; return ([],t) }) ++
+ (do { (",",t) <- lex s ; (x,u) <- readx t ; (xs,v) <- readl2 u ; return (x:xs,v) })
+
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Lexical analysis}
+%* *
+%*********************************************************
+
+This lexer is not completely faithful to the Haskell lexical syntax.
+Current limitations:
+ Qualified names are not handled properly
+ A `--' does not terminate a symbol
+ Octal and hexidecimal numerics are not recognized as a single token
+
+\begin{code}
+lex :: ReadS String
+
+lex "" = return ("","")
+lex (c:s) | isSpace c = lex (dropWhile isSpace s)
+lex ('\'':s) = do
+ (ch, '\'':t) <- lexLitChar s
+ guard (ch /= "'")
+ return ('\'':ch++"'", t)
+lex ('"':s) = do
+ (str,t) <- lexString s
+ return ('"':str, t)
+
+ where
+ lexString ('"':s) = return ("\"",s)
+ lexString s = do
+ (ch,t) <- lexStrItem s
+ (str,u) <- lexString t
+ return (ch++str, u)
+
+
+ lexStrItem ('\\':'&':s) = return ("\\&",s)
+ lexStrItem ('\\':c:s) | isSpace c = do
+ ('\\':t) <- return (dropWhile isSpace s)
+ return ("\\&",t)
+ lexStrItem s = lexLitChar s
+
+lex (c:s) | isSingle c = return ([c],s)
+ | isSym c = do
+ (sym,t) <- return (span isSym s)
+ return (c:sym,t)
+ | isAlpha c = do
+ (nam,t) <- return (span isIdChar s)
+ return (c:nam, t)
+ | isDigit c = do
+{- Removed, 13/03/2000 by SDM.
+ Doesn't work, and not required by Haskell report.
+ let
+ (pred, s', isDec) =
+ case s of
+ ('o':rs) -> (isOctDigit, rs, False)
+ ('O':rs) -> (isOctDigit, rs, False)
+ ('x':rs) -> (isHexDigit, rs, False)
+ ('X':rs) -> (isHexDigit, rs, False)
+ _ -> (isDigit, s, True)
+-}
+ (ds,s) <- return (span isDigit s)
+ (fe,t) <- lexFracExp s
+ return (c:ds++fe,t)
+ | otherwise = mzero -- bad character
+ where
+ isSingle c = c `elem` ",;()[]{}_`"
+ isSym c = c `elem` "!@#$%&*+./<=>?\\^|:-~"
+ isIdChar c = isAlphaNum c || c `elem` "_'"
+
+ lexFracExp ('.':c:cs) | isDigit c = do
+ (ds,t) <- lex0Digits cs
+ (e,u) <- lexExp t
+ return ('.':c:ds++e,u)
+ lexFracExp s = return ("",s)
+
+ lexExp (e:s) | e `elem` "eE" =
+ (do
+ (c:t) <- return s
+ guard (c `elem` "+-")
+ (ds,u) <- lexDecDigits t
+ return (e:c:ds,u)) ++
+ (do
+ (ds,t) <- lexDecDigits s
+ return (e:ds,t))
+
+ lexExp s = return ("",s)
+
+lexDigits :: ReadS String
+lexDigits = lexDecDigits
+
+lexDecDigits :: ReadS String
+lexDecDigits = nonnull isDigit
+
+lexOctDigits :: ReadS String
+lexOctDigits = nonnull isOctDigit
+
+lexHexDigits :: ReadS String
+lexHexDigits = nonnull isHexDigit
+
+-- 0 or more digits
+lex0Digits :: ReadS String
+lex0Digits s = return (span isDigit s)
+
+nonnull :: (Char -> Bool) -> ReadS String
+nonnull p s = do
+ (cs@(_:_),t) <- return (span p s)
+ return (cs,t)
+
+lexLitChar :: ReadS String
+lexLitChar ('\\':s) = do
+ (esc,t) <- lexEsc s
+ return ('\\':esc, t)
+ where
+ lexEsc (c:s) | c `elem` escChars = return ([c],s)
+ lexEsc s@(d:_) | isDigit d = checkSize 10 lexDecDigits s
+ lexEsc ('o':d:s) | isOctDigit d = checkSize 8 lexOctDigits (d:s)
+ lexEsc ('O':d:s) | isOctDigit d = checkSize 8 lexOctDigits (d:s)
+ lexEsc ('x':d:s) | isHexDigit d = checkSize 16 lexHexDigits (d:s)
+ lexEsc ('X':d:s) | isHexDigit d = checkSize 16 lexHexDigits (d:s)
+ lexEsc ('^':c:s) | c >= '@' && c <= '_' = [(['^',c],s)] -- cf. cntrl in 2.6 of H. report.
+ lexEsc s@(c:_) | isUpper c = fromAsciiLab s
+ lexEsc _ = mzero
+
+ escChars = "abfnrtv\\\"'"
+
+ fromAsciiLab (x:y:z:ls) | isUpper y && (isUpper z || isDigit z) &&
+ [x,y,z] `elem` asciiEscTab = return ([x,y,z], ls)
+ fromAsciiLab (x:y:ls) | isUpper y &&
+ [x,y] `elem` asciiEscTab = return ([x,y], ls)
+ fromAsciiLab _ = mzero
+
+ asciiEscTab = "DEL" : asciiTab
+
+ {-
+ Check that the numerically escaped char literals are
+ within accepted boundaries.
+
+ Note: this allows char lits with leading zeros, i.e.,
+ \0000000000000000000000000000001.
+ -}
+ checkSize base f str = do
+ (num, res) <- f str
+ if toAnInteger base num > toInteger (ord maxBound) then
+ mzero
+ else
+ case base of
+ 8 -> return ('o':num, res)
+ 16 -> return ('x':num, res)
+ _ -> return (num, res)
+
+ toAnInteger base = foldl (\ acc n -> acc*base + toInteger (digitToInt n)) 0
+
+
+lexLitChar (c:s) = return ([c],s)
+lexLitChar "" = mzero
+
+digitToInt :: Char -> Int
+digitToInt c
+ | isDigit c = fromEnum c - fromEnum '0'
+ | c >= 'a' && c <= 'f' = fromEnum c - fromEnum 'a' + 10
+ | c >= 'A' && c <= 'F' = fromEnum c - fromEnum 'A' + 10
+ | otherwise = error ("Char.digitToInt: not a digit " ++ show c) -- sigh
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Instances of @Read@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Read Char where
+ readsPrec _ = readParen False
+ (\r -> do
+ ('\'':s,t) <- lex r
+ (c,"\'") <- readLitChar s
+ return (c,t))
+
+ readList = readParen False (\r -> do
+ ('"':s,t) <- lex r
+ (l,_) <- readl s
+ return (l,t))
+ where readl ('"':s) = return ("",s)
+ readl ('\\':'&':s) = readl s
+ readl s = do
+ (c,t) <- readLitChar s
+ (cs,u) <- readl t
+ return (c:cs,u)
+
+instance Read Bool where
+ readsPrec _ = readParen False
+ (\r ->
+ lex r >>= \ lr ->
+ (do { ("True", rest) <- return lr ; return (True, rest) }) ++
+ (do { ("False", rest) <- return lr ; return (False, rest) }))
+
+
+instance Read Ordering where
+ readsPrec _ = readParen False
+ (\r ->
+ lex r >>= \ lr ->
+ (do { ("LT", rest) <- return lr ; return (LT, rest) }) ++
+ (do { ("EQ", rest) <- return lr ; return (EQ, rest) }) ++
+ (do { ("GT", rest) <- return lr ; return (GT, rest) }))
+
+instance Read a => Read (Maybe a) where
+ readsPrec _ = readParen False
+ (\r ->
+ lex r >>= \ lr ->
+ (do { ("Nothing", rest) <- return lr ; return (Nothing, rest)}) ++
+ (do
+ ("Just", rest1) <- return lr
+ (x, rest2) <- reads rest1
+ return (Just x, rest2)))
+
+instance (Read a, Read b) => Read (Either a b) where
+ readsPrec _ = readParen False
+ (\r ->
+ lex r >>= \ lr ->
+ (do
+ ("Left", rest1) <- return lr
+ (x, rest2) <- reads rest1
+ return (Left x, rest2)) ++
+ (do
+ ("Right", rest1) <- return lr
+ (x, rest2) <- reads rest1
+ return (Right x, rest2)))
+
+instance Read Int where
+ readsPrec _ x = readSigned readDec x
+
+instance Read Integer where
+ readsPrec _ x = readSigned readDec x
+
+instance Read Float where
+ readsPrec _ x = readSigned readFloat x
+
+instance Read Double where
+ readsPrec _ x = readSigned readFloat x
+
+instance (Integral a, Read a) => Read (Ratio a) where
+ readsPrec p = readParen (p > ratio_prec)
+ (\r -> do
+ (x,s) <- reads r
+ ("%",t) <- lex s
+ (y,u) <- reads t
+ return (x%y,u))
+
+instance (Read a) => Read [a] where
+ readsPrec _ = readList
+
+instance Read () where
+ readsPrec _ = readParen False
+ (\r -> do
+ ("(",s) <- lex r
+ (")",t) <- lex s
+ return ((),t))
+
+instance (Read a, Read b) => Read (a,b) where
+ readsPrec _ = readParen False
+ (\r -> do
+ ("(",s) <- lex r
+ (x,t) <- readsPrec 0 s
+ (",",u) <- lex t
+ (y,v) <- readsPrec 0 u
+ (")",w) <- lex v
+ return ((x,y), w))
+
+instance (Read a, Read b, Read c) => Read (a, b, c) where
+ readsPrec _ = readParen False
+ (\a -> do
+ ("(",b) <- lex a
+ (x,c) <- readsPrec 0 b
+ (",",d) <- lex c
+ (y,e) <- readsPrec 0 d
+ (",",f) <- lex e
+ (z,g) <- readsPrec 0 f
+ (")",h) <- lex g
+ return ((x,y,z), h))
+
+instance (Read a, Read b, Read c, Read d) => Read (a, b, c, d) where
+ readsPrec _ = readParen False
+ (\a -> do
+ ("(",b) <- lex a
+ (w,c) <- readsPrec 0 b
+ (",",d) <- lex c
+ (x,e) <- readsPrec 0 d
+ (",",f) <- lex e
+ (y,g) <- readsPrec 0 f
+ (",",h) <- lex g
+ (z,h) <- readsPrec 0 h
+ (")",i) <- lex h
+ return ((w,x,y,z), i))
+
+instance (Read a, Read b, Read c, Read d, Read e) => Read (a, b, c, d, e) where
+ readsPrec _ = readParen False
+ (\a -> do
+ ("(",b) <- lex a
+ (v,c) <- readsPrec 0 b
+ (",",d) <- lex c
+ (w,e) <- readsPrec 0 d
+ (",",f) <- lex e
+ (x,g) <- readsPrec 0 f
+ (",",h) <- lex g
+ (y,i) <- readsPrec 0 h
+ (",",j) <- lex i
+ (z,k) <- readsPrec 0 j
+ (")",l) <- lex k
+ return ((v,w,x,y,z), l))
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Reading characters}
+%* *
+%*********************************************************
+
+\begin{code}
+readLitChar :: ReadS Char
+
+readLitChar [] = mzero
+readLitChar ('\\':s) = readEsc s
+ where
+ readEsc ('a':s) = return ('\a',s)
+ readEsc ('b':s) = return ('\b',s)
+ readEsc ('f':s) = return ('\f',s)
+ readEsc ('n':s) = return ('\n',s)
+ readEsc ('r':s) = return ('\r',s)
+ readEsc ('t':s) = return ('\t',s)
+ readEsc ('v':s) = return ('\v',s)
+ readEsc ('\\':s) = return ('\\',s)
+ readEsc ('"':s) = return ('"',s)
+ readEsc ('\'':s) = return ('\'',s)
+ readEsc ('^':c:s) | c >= '@' && c <= '_'
+ = return (chr (ord c - ord '@'), s)
+ readEsc s@(d:_) | isDigit d
+ = do
+ (n,t) <- readDec s
+ return (chr n,t)
+ readEsc ('o':s) = do
+ (n,t) <- readOct s
+ return (chr n,t)
+ readEsc ('x':s) = do
+ (n,t) <- readHex s
+ return (chr n,t)
+
+ readEsc s@(c:_) | isUpper c
+ = let table = ('\DEL', "DEL") : zip ['\NUL'..] asciiTab
+ in case [(c,s') | (c, mne) <- table,
+ ([],s') <- [match mne s]]
+ of (pr:_) -> return pr
+ [] -> mzero
+ readEsc _ = mzero
+
+readLitChar (c:s) = return (c,s)
+
+match :: (Eq a) => [a] -> [a] -> ([a],[a])
+match (x:xs) (y:ys) | x == y = match xs ys
+match xs ys = (xs,ys)
+
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Reading numbers}
+%* *
+%*********************************************************
+
+Note: reading numbers at bases different than 10, does not
+include lexing common prefixes such as '0x' or '0o' etc.
+
+\begin{code}
+{-# SPECIALISE readDec ::
+ ReadS Int,
+ ReadS Integer #-}
+readDec :: (Integral a) => ReadS a
+readDec = readInt 10 isDigit (\d -> ord d - ord '0')
+
+{-# SPECIALISE readOct ::
+ ReadS Int,
+ ReadS Integer #-}
+readOct :: (Integral a) => ReadS a
+readOct = readInt 8 isOctDigit (\d -> ord d - ord '0')
+
+{-# SPECIALISE readHex ::
+ ReadS Int,
+ ReadS Integer #-}
+readHex :: (Integral a) => ReadS a
+readHex = readInt 16 isHexDigit hex
+ where hex d = ord d - (if isDigit d then ord '0'
+ else ord (if isUpper d then 'A' else 'a') - 10)
+
+readInt :: (Integral a) => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a
+readInt radix isDig digToInt s = do
+ (ds,r) <- nonnull isDig s
+ return (foldl1 (\n d -> n * radix + d)
+ (map (fromInteger . toInteger . digToInt) ds), r)
+
+{-# SPECIALISE readSigned ::
+ ReadS Int -> ReadS Int,
+ ReadS Integer -> ReadS Integer,
+ ReadS Double -> ReadS Double #-}
+readSigned :: (Real a) => ReadS a -> ReadS a
+readSigned readPos = readParen False read'
+ where read' r = read'' r ++
+ (do
+ ("-",s) <- lex r
+ (x,t) <- read'' s
+ return (-x,t))
+ read'' r = do
+ (str,s) <- lex r
+ (n,"") <- readPos str
+ return (n,s)
+\end{code}
+
+The functions readFloat below uses rational arithmetic
+to ensure correct conversion between the floating-point radix and
+decimal. It is often possible to use a higher-precision floating-
+point type to obtain the same results.
+
+\begin{code}
+{-# SPECIALISE readFloat ::
+ ReadS Double,
+ ReadS Float #-}
+readFloat :: (RealFloat a) => ReadS a
+readFloat r = do
+ (x,t) <- readRational r
+ return (fromRational x,t)
+
+readRational :: ReadS Rational -- NB: doesn't handle leading "-"
+
+readRational r =
+ (do
+ (n,d,s) <- readFix r
+ (k,t) <- readExp s
+ return ((n%1)*10^^(k-d), t )) ++
+ (do
+ ("NaN",t) <- lex r
+ return (0/0,t) ) ++
+ (do
+ ("Infinity",t) <- lex r
+ return (1/0,t) )
+ where
+ readFix r = do
+ (ds,s) <- lexDecDigits r
+ (ds',t) <- lexDotDigits s
+ return (read (ds++ds'), length ds', t)
+
+ readExp (e:s) | e `elem` "eE" = readExp' s
+ readExp s = return (0,s)
+
+ readExp' ('+':s) = readDec s
+ readExp' ('-':s) = do
+ (k,t) <- readDec s
+ return (-k,t)
+ readExp' s = readDec s
+
+ lexDotDigits ('.':s) = lex0Digits s
+ lexDotDigits s = return ("",s)
+
+readRational__ :: String -> Rational -- we export this one (non-std)
+ -- NB: *does* handle a leading "-"
+readRational__ top_s
+ = case top_s of
+ '-' : xs -> - (read_me xs)
+ xs -> read_me xs
+ where
+ read_me s
+ = case (do { (x,t) <- readRational s ; ("","") <- lex t ; return x }) of
+#ifndef NEW_READS_REP
+ [x] -> x
+ [] -> error ("readRational__: no parse:" ++ top_s)
+ _ -> error ("readRational__: ambiguous parse:" ++ top_s)
+#else
+ Just x -> x
+ Nothing -> error ("readRational__: no parse:" ++ top_s)
+#endif
+
+\end{code}
diff --git a/libraries/base/GHC/Real.lhs b/libraries/base/GHC/Real.lhs
new file mode 100644
index 0000000000..b453f6b6eb
--- /dev/null
+++ b/libraries/base/GHC/Real.lhs
@@ -0,0 +1,369 @@
+% ------------------------------------------------------------------------------
+% $Id: Real.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1994-2000
+%
+
+\section[GHC.Real]{Module @GHC.Real@}
+
+The types
+
+ Ratio, Rational
+
+and the classes
+
+ Real
+ Integral
+ Fractional
+ RealFrac
+
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Real where
+
+import {-# SOURCE #-} GHC.Err
+import GHC.Base
+import GHC.Num
+import GHC.List
+import GHC.Enum
+import GHC.Show
+
+infixr 8 ^, ^^
+infixl 7 /, `quot`, `rem`, `div`, `mod`
+
+default () -- Double isn't available yet,
+ -- and we shouldn't be using defaults anyway
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{The @Ratio@ and @Rational@ types}
+%* *
+%*********************************************************
+
+\begin{code}
+data (Integral a) => Ratio a = !a :% !a deriving (Eq)
+type Rational = Ratio Integer
+\end{code}
+
+
+\begin{code}
+{-# SPECIALISE (%) :: Integer -> Integer -> Rational #-}
+(%) :: (Integral a) => a -> a -> Ratio a
+numerator, denominator :: (Integral a) => Ratio a -> a
+\end{code}
+
+\tr{reduce} is a subsidiary function used only in this module .
+It normalises a ratio by dividing both numerator and denominator by
+their greatest common divisor.
+
+\begin{code}
+reduce :: (Integral a) => a -> a -> Ratio a
+reduce _ 0 = error "Ratio.%: zero denominator"
+reduce x y = (x `quot` d) :% (y `quot` d)
+ where d = gcd x y
+\end{code}
+
+\begin{code}
+x % y = reduce (x * signum y) (abs y)
+
+numerator (x :% _) = x
+denominator (_ :% y) = y
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Standard numeric classes}
+%* *
+%*********************************************************
+
+\begin{code}
+class (Num a, Ord a) => Real a where
+ toRational :: a -> Rational
+
+class (Real a, Enum a) => Integral a where
+ quot, rem, div, mod :: a -> a -> a
+ quotRem, divMod :: a -> a -> (a,a)
+ toInteger :: a -> Integer
+
+ n `quot` d = q where (q,_) = quotRem n d
+ n `rem` d = r where (_,r) = quotRem n d
+ n `div` d = q where (q,_) = divMod n d
+ n `mod` d = r where (_,r) = divMod n d
+ divMod n d = if signum r == negate (signum d) then (q-1, r+d) else qr
+ where qr@(q,r) = quotRem n d
+
+class (Num a) => Fractional a where
+ (/) :: a -> a -> a
+ recip :: a -> a
+ fromRational :: Rational -> a
+
+ recip x = 1 / x
+ x / y = x * recip y
+
+class (Real a, Fractional a) => RealFrac a where
+ properFraction :: (Integral b) => a -> (b,a)
+ truncate, round :: (Integral b) => a -> b
+ ceiling, floor :: (Integral b) => a -> b
+
+ truncate x = m where (m,_) = properFraction x
+
+ round x = let (n,r) = properFraction x
+ m = if r < 0 then n - 1 else n + 1
+ in case signum (abs r - 0.5) of
+ -1 -> n
+ 0 -> if even n then n else m
+ 1 -> m
+
+ ceiling x = if r > 0 then n + 1 else n
+ where (n,r) = properFraction x
+
+ floor x = if r < 0 then n - 1 else n
+ where (n,r) = properFraction x
+\end{code}
+
+
+These 'numeric' enumerations come straight from the Report
+
+\begin{code}
+numericEnumFrom :: (Fractional a) => a -> [a]
+numericEnumFrom = iterate (+1)
+
+numericEnumFromThen :: (Fractional a) => a -> a -> [a]
+numericEnumFromThen n m = iterate (+(m-n)) n
+
+numericEnumFromTo :: (Ord a, Fractional a) => a -> a -> [a]
+numericEnumFromTo n m = takeWhile (<= m + 1/2) (numericEnumFrom n)
+
+numericEnumFromThenTo :: (Ord a, Fractional a) => a -> a -> a -> [a]
+numericEnumFromThenTo e1 e2 e3 = takeWhile pred (numericEnumFromThen e1 e2)
+ where
+ mid = (e2 - e1) / 2
+ pred | e2 > e1 = (<= e3 + mid)
+ | otherwise = (>= e3 + mid)
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Instances for @Int@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Real Int where
+ toRational x = toInteger x % 1
+
+instance Integral Int where
+ toInteger i = int2Integer i -- give back a full-blown Integer
+
+ -- Following chks for zero divisor are non-standard (WDP)
+ a `quot` b = if b /= 0
+ then a `quotInt` b
+ else error "Prelude.Integral.quot{Int}: divide by 0"
+ a `rem` b = if b /= 0
+ then a `remInt` b
+ else error "Prelude.Integral.rem{Int}: divide by 0"
+
+ x `div` y = x `divInt` y
+ x `mod` y = x `modInt` y
+
+ a `quotRem` b = a `quotRemInt` b
+ a `divMod` b = a `divModInt` b
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Instances for @Integer@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance Real Integer where
+ toRational x = x % 1
+
+instance Integral Integer where
+ toInteger n = n
+
+ n `quot` d = n `quotInteger` d
+ n `rem` d = n `remInteger` d
+
+ n `div` d = q where (q,_) = divMod n d
+ n `mod` d = r where (_,r) = divMod n d
+
+ a `divMod` b = a `divModInteger` b
+ a `quotRem` b = a `quotRemInteger` b
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Instances for @Ratio@}
+%* *
+%*********************************************************
+
+\begin{code}
+instance (Integral a) => Ord (Ratio a) where
+ {-# SPECIALIZE instance Ord Rational #-}
+ (x:%y) <= (x':%y') = x * y' <= x' * y
+ (x:%y) < (x':%y') = x * y' < x' * y
+
+instance (Integral a) => Num (Ratio a) where
+ {-# SPECIALIZE instance Num Rational #-}
+ (x:%y) + (x':%y') = reduce (x*y' + x'*y) (y*y')
+ (x:%y) - (x':%y') = reduce (x*y' - x'*y) (y*y')
+ (x:%y) * (x':%y') = reduce (x * x') (y * y')
+ negate (x:%y) = (-x) :% y
+ abs (x:%y) = abs x :% y
+ signum (x:%_) = signum x :% 1
+ fromInteger x = fromInteger x :% 1
+
+instance (Integral a) => Fractional (Ratio a) where
+ {-# SPECIALIZE instance Fractional Rational #-}
+ (x:%y) / (x':%y') = (x*y') % (y*x')
+ recip (x:%y) = if x < 0 then (-y) :% (-x) else y :% x
+ fromRational (x:%y) = fromInteger x :% fromInteger y
+
+instance (Integral a) => Real (Ratio a) where
+ {-# SPECIALIZE instance Real Rational #-}
+ toRational (x:%y) = toInteger x :% toInteger y
+
+instance (Integral a) => RealFrac (Ratio a) where
+ {-# SPECIALIZE instance RealFrac Rational #-}
+ properFraction (x:%y) = (fromInteger (toInteger q), r:%y)
+ where (q,r) = quotRem x y
+
+instance (Integral a) => Show (Ratio a) where
+ {-# SPECIALIZE instance Show Rational #-}
+ showsPrec p (x:%y) = showParen (p > ratio_prec)
+ (shows x . showString " % " . shows y)
+
+ratio_prec :: Int
+ratio_prec = 7
+
+instance (Integral a) => Enum (Ratio a) where
+ {-# SPECIALIZE instance Enum Rational #-}
+ succ x = x + 1
+ pred x = x - 1
+
+ toEnum n = fromInteger (int2Integer n) :% 1
+ fromEnum = fromInteger . truncate
+
+ enumFrom = numericEnumFrom
+ enumFromThen = numericEnumFromThen
+ enumFromTo = numericEnumFromTo
+ enumFromThenTo = numericEnumFromThenTo
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Coercions}
+%* *
+%*********************************************************
+
+\begin{code}
+fromIntegral :: (Integral a, Num b) => a -> b
+fromIntegral = fromInteger . toInteger
+
+{-# RULES
+"fromIntegral/Int->Int" fromIntegral = id :: Int -> Int
+ #-}
+
+realToFrac :: (Real a, Fractional b) => a -> b
+realToFrac = fromRational . toRational
+
+{-# RULES
+"realToFrac/Int->Int" realToFrac = id :: Int -> Int
+ #-}
+
+-- For backward compatibility
+{-# DEPRECATED fromInt "use fromIntegral instead" #-}
+fromInt :: Num a => Int -> a
+fromInt = fromIntegral
+
+-- For backward compatibility
+{-# DEPRECATED toInt "use fromIntegral instead" #-}
+toInt :: Integral a => a -> Int
+toInt = fromIntegral
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Overloaded numeric functions}
+%* *
+%*********************************************************
+
+\begin{code}
+showSigned :: (Real a) => (a -> ShowS) -> Int -> a -> ShowS
+showSigned showPos p x
+ | x < 0 = showParen (p > 6) (showChar '-' . showPos (-x))
+ | otherwise = showPos x
+
+even, odd :: (Integral a) => a -> Bool
+even n = n `rem` 2 == 0
+odd = not . even
+
+-------------------------------------------------------
+{-# SPECIALISE (^) ::
+ Integer -> Integer -> Integer,
+ Integer -> Int -> Integer,
+ Int -> Int -> Int #-}
+(^) :: (Num a, Integral b) => a -> b -> a
+_ ^ 0 = 1
+x ^ n | n > 0 = f x (n-1) x
+ where f _ 0 y = y
+ f a d y = g a d where
+ g b i | even i = g (b*b) (i `quot` 2)
+ | otherwise = f b (i-1) (b*y)
+_ ^ _ = error "Prelude.^: negative exponent"
+
+{-# SPECIALISE (^^) ::
+ Rational -> Int -> Rational #-}
+(^^) :: (Fractional a, Integral b) => a -> b -> a
+x ^^ n = if n >= 0 then x^n else recip (x^(negate n))
+
+
+-------------------------------------------------------
+gcd :: (Integral a) => a -> a -> a
+gcd 0 0 = error "Prelude.gcd: gcd 0 0 is undefined"
+gcd x y = gcd' (abs x) (abs y)
+ where gcd' a 0 = a
+ gcd' a b = gcd' b (a `rem` b)
+
+lcm :: (Integral a) => a -> a -> a
+{-# SPECIALISE lcm :: Int -> Int -> Int #-}
+lcm _ 0 = 0
+lcm 0 _ = 0
+lcm x y = abs ((x `quot` (gcd x y)) * y)
+
+
+{-# RULES
+"gcd/Int->Int->Int" gcd = gcdInt
+"gcd/Integer->Integer->Integer" gcd = gcdInteger
+"lcm/Integer->Integer->Integer" lcm = lcmInteger
+ #-}
+
+integralEnumFrom :: (Integral a, Bounded a) => a -> [a]
+integralEnumFrom n = map fromInteger [toInteger n .. toInteger (maxBound `asTypeOf` n)]
+
+integralEnumFromThen :: (Integral a, Bounded a) => a -> a -> [a]
+integralEnumFromThen n1 n2
+ | i_n2 >= i_n1 = map fromInteger [i_n1, i_n2 .. toInteger (maxBound `asTypeOf` n1)]
+ | otherwise = map fromInteger [i_n1, i_n2 .. toInteger (minBound `asTypeOf` n1)]
+ where
+ i_n1 = toInteger n1
+ i_n2 = toInteger n2
+
+integralEnumFromTo :: Integral a => a -> a -> [a]
+integralEnumFromTo n m = map fromInteger [toInteger n .. toInteger m]
+
+integralEnumFromThenTo :: Integral a => a -> a -> a -> [a]
+integralEnumFromThenTo n1 n2 m
+ = map fromInteger [toInteger n1, toInteger n2 .. toInteger m]
+\end{code}
diff --git a/libraries/base/GHC/ST.lhs b/libraries/base/GHC/ST.lhs
new file mode 100644
index 0000000000..f98b33d73d
--- /dev/null
+++ b/libraries/base/GHC/ST.lhs
@@ -0,0 +1,127 @@
+% ------------------------------------------------------------------------------
+% $Id: ST.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1992-2000
+%
+
+\section[GHC.ST]{The @ST@ monad}
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.ST where
+
+import GHC.Base
+import GHC.Show
+import GHC.Num
+
+default ()
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{The @ST@ monad}
+%* *
+%*********************************************************
+
+The state-transformer monad proper. By default the monad is strict;
+too many people got bitten by space leaks when it was lazy.
+
+\begin{code}
+newtype ST s a = ST (STRep s a)
+type STRep s a = State# s -> (# State# s, a #)
+
+instance Functor (ST s) where
+ fmap f (ST m) = ST $ \ s ->
+ case (m s) of { (# new_s, r #) ->
+ (# new_s, f r #) }
+
+instance Monad (ST s) where
+ {-# INLINE return #-}
+ {-# INLINE (>>) #-}
+ {-# INLINE (>>=) #-}
+ return x = ST $ \ s -> (# s, x #)
+ m >> k = m >>= \ _ -> k
+
+ (ST m) >>= k
+ = ST $ \ s ->
+ case (m s) of { (# new_s, r #) ->
+ case (k r) of { ST k2 ->
+ (k2 new_s) }}
+
+data STret s a = STret (State# s) a
+
+-- liftST is useful when we want a lifted result from an ST computation. See
+-- fixST below.
+liftST :: ST s a -> State# s -> STret s a
+liftST (ST m) = \s -> case m s of (# s', r #) -> STret s' r
+
+{-# NOINLINE unsafeInterleaveST #-}
+unsafeInterleaveST :: ST s a -> ST s a
+unsafeInterleaveST (ST m) = ST ( \ s ->
+ let
+ r = case m s of (# _, res #) -> res
+ in
+ (# s, r #)
+ )
+
+fixST :: (a -> ST s a) -> ST s a
+fixST k = ST $ \ s ->
+ let ans = liftST (k r) s
+ STret _ r = ans
+ in
+ case ans of STret s' x -> (# s', x #)
+
+instance Show (ST s a) where
+ showsPrec _ _ = showString "<<ST action>>"
+ showList = showList__ (showsPrec 0)
+\end{code}
+
+Definition of runST
+~~~~~~~~~~~~~~~~~~~
+
+SLPJ 95/04: Why @runST@ must not have an unfolding; consider:
+\begin{verbatim}
+f x =
+ runST ( \ s -> let
+ (a, s') = newArray# 100 [] s
+ (_, s'') = fill_in_array_or_something a x s'
+ in
+ freezeArray# a s'' )
+\end{verbatim}
+If we inline @runST@, we'll get:
+\begin{verbatim}
+f x = let
+ (a, s') = newArray# 100 [] realWorld#{-NB-}
+ (_, s'') = fill_in_array_or_something a x s'
+ in
+ freezeArray# a s''
+\end{verbatim}
+And now the @newArray#@ binding can be floated to become a CAF, which
+is totally and utterly wrong:
+\begin{verbatim}
+f = let
+ (a, s') = newArray# 100 [] realWorld#{-NB-} -- YIKES!!!
+ in
+ \ x ->
+ let (_, s'') = fill_in_array_or_something a x s' in
+ freezeArray# a s''
+\end{verbatim}
+All calls to @f@ will share a {\em single} array! End SLPJ 95/04.
+
+\begin{code}
+{-# INLINE runST #-}
+-- The INLINE prevents runSTRep getting inlined in *this* module
+-- so that it is still visible when runST is inlined in an importing
+-- module. Regrettably delicate. runST is behaving like a wrapper.
+runST :: (forall s. ST s a) -> a
+runST st = runSTRep (case st of { ST st_rep -> st_rep })
+
+-- I'm only letting runSTRep be inlined right at the end, in particular *after* full laziness
+-- That's what the "INLINE 100" says.
+-- SLPJ Apr 99
+{-# INLINE 100 runSTRep #-}
+runSTRep :: (forall s. STRep s a) -> a
+runSTRep st_rep = case st_rep realWorld# of
+ (# _, r #) -> r
+\end{code}
diff --git a/libraries/base/GHC/STRef.lhs b/libraries/base/GHC/STRef.lhs
new file mode 100644
index 0000000000..cf9cea5efe
--- /dev/null
+++ b/libraries/base/GHC/STRef.lhs
@@ -0,0 +1,30 @@
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+module GHC.STRef where
+
+import GHC.ST
+import GHC.Prim
+import GHC.Base
+
+data STRef s a = STRef (MutVar# s a)
+
+newSTRef :: a -> ST s (STRef s a)
+newSTRef init = ST $ \s1# ->
+ case newMutVar# init s1# of { (# s2#, var# #) ->
+ (# s2#, STRef var# #) }
+
+readSTRef :: STRef s a -> ST s a
+readSTRef (STRef var#) = ST $ \s1# -> readMutVar# var# s1#
+
+writeSTRef :: STRef s a -> a -> ST s ()
+writeSTRef (STRef var#) val = ST $ \s1# ->
+ case writeMutVar# var# val s1# of { s2# ->
+ (# s2#, () #) }
+
+modifySTRef :: STRef s a -> (a -> a) -> ST s ()
+modifySTRef ref f = readSTRef ref >>= writeSTRef ref . f
+
+-- Just pointer equality on mutable references:
+instance Eq (STRef s a) where
+ STRef v1# == STRef v2# = sameMutVar# v1# v2#
+\end{code}
diff --git a/libraries/base/GHC/Show.lhs b/libraries/base/GHC/Show.lhs
new file mode 100644
index 0000000000..2edd0383de
--- /dev/null
+++ b/libraries/base/GHC/Show.lhs
@@ -0,0 +1,378 @@
+% ------------------------------------------------------------------------------
+% $Id: Show.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1992-2000
+%
+
+\section{Module @GHC.Show@}
+
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Show
+ (
+ Show(..), ShowS,
+
+ -- Instances for Show: (), [], Bool, Ordering, Int, Char
+
+ -- Show support code
+ shows, showChar, showString, showParen, showList__, showSpace,
+ showLitChar, protectEsc,
+ intToDigit, showSignedInt,
+
+ -- Character operations
+ isAscii, isLatin1, isControl, isPrint, isSpace, isUpper,
+ isLower, isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum,
+ toUpper, toLower,
+ asciiTab,
+
+ -- String operations
+ lines, unlines, words, unwords
+ )
+ where
+
+import {-# SOURCE #-} GHC.Err ( error )
+import GHC.Base
+import GHC.Tup
+import GHC.Maybe
+import GHC.List ( (!!), break, dropWhile
+#ifdef USE_REPORT_PRELUDE
+ , concatMap, foldr1
+#endif
+ )
+\end{code}
+
+
+
+%*********************************************************
+%* *
+\subsection{The @Show@ class}
+%* *
+%*********************************************************
+
+\begin{code}
+type ShowS = String -> String
+
+class Show a where
+ showsPrec :: Int -> a -> ShowS
+ show :: a -> String
+ showList :: [a] -> ShowS
+
+ showsPrec _ x s = show x ++ s
+ show x = shows x ""
+ showList ls s = showList__ shows ls s
+
+showList__ :: (a -> ShowS) -> [a] -> ShowS
+showList__ _ [] s = "[]" ++ s
+showList__ showx (x:xs) s = '[' : showx x (showl xs)
+ where
+ showl [] = ']' : s
+ showl (y:ys) = ',' : showx y (showl ys)
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Simple Instances}
+%* *
+%*********************************************************
+
+\begin{code}
+
+instance Show () where
+ showsPrec _ () = showString "()"
+
+instance Show a => Show [a] where
+ showsPrec _ = showList
+
+instance Show Bool where
+ showsPrec _ True = showString "True"
+ showsPrec _ False = showString "False"
+
+instance Show Ordering where
+ showsPrec _ LT = showString "LT"
+ showsPrec _ EQ = showString "EQ"
+ showsPrec _ GT = showString "GT"
+
+instance Show Char where
+ showsPrec _ '\'' = showString "'\\''"
+ showsPrec _ c = showChar '\'' . showLitChar c . showChar '\''
+
+ showList cs = showChar '"' . showl cs
+ where showl "" s = showChar '"' s
+ showl ('"':xs) s = showString "\\\"" (showl xs s)
+ showl (x:xs) s = showLitChar x (showl xs s)
+ -- Making 's' an explicit parameter makes it clear to GHC
+ -- that showl has arity 2, which avoids it allocating an extra lambda
+ -- The sticking point is the recursive call to (showl xs), which
+ -- it can't figure out would be ok with arity 2.
+
+instance Show Int where
+ showsPrec = showSignedInt
+
+instance Show a => Show (Maybe a) where
+ showsPrec _p Nothing s = showString "Nothing" s
+ showsPrec (I# p#) (Just x) s
+ = (showParen (p# >=# 10#) $
+ showString "Just " .
+ showsPrec (I# 10#) x) s
+
+instance (Show a, Show b) => Show (Either a b) where
+ showsPrec (I# p#) e s =
+ (showParen (p# >=# 10#) $
+ case e of
+ Left a -> showString "Left " . showsPrec (I# 10#) a
+ Right b -> showString "Right " . showsPrec (I# 10#) b)
+ s
+
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Show instances for the first few tuples
+%* *
+%*********************************************************
+
+\begin{code}
+-- The explicit 's' parameters are important
+-- Otherwise GHC thinks that "shows x" might take a lot of work to compute
+-- and generates defns like
+-- showsPrec _ (x,y) = let sx = shows x; sy = shows y in
+-- \s -> showChar '(' (sx (showChar ',' (sy (showChar ')' s))))
+
+instance (Show a, Show b) => Show (a,b) where
+ showsPrec _ (x,y) s = (showChar '(' . shows x . showChar ',' .
+ shows y . showChar ')')
+ s
+
+instance (Show a, Show b, Show c) => Show (a, b, c) where
+ showsPrec _ (x,y,z) s = (showChar '(' . shows x . showChar ',' .
+ shows y . showChar ',' .
+ shows z . showChar ')')
+ s
+
+instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where
+ showsPrec _ (w,x,y,z) s = (showChar '(' . shows w . showChar ',' .
+ shows x . showChar ',' .
+ shows y . showChar ',' .
+ shows z . showChar ')')
+ s
+
+instance (Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e) where
+ showsPrec _ (v,w,x,y,z) s = (showChar '(' . shows v . showChar ',' .
+ shows w . showChar ',' .
+ shows x . showChar ',' .
+ shows y . showChar ',' .
+ shows z . showChar ')')
+ s
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Support code for @Show@}
+%* *
+%*********************************************************
+
+\begin{code}
+shows :: (Show a) => a -> ShowS
+shows = showsPrec zeroInt
+
+showChar :: Char -> ShowS
+showChar = (:)
+
+showString :: String -> ShowS
+showString = (++)
+
+showParen :: Bool -> ShowS -> ShowS
+showParen b p = if b then showChar '(' . p . showChar ')' else p
+
+showSpace :: ShowS
+showSpace = {-showChar ' '-} \ xs -> ' ' : xs
+\end{code}
+
+Code specific for characters
+
+\begin{code}
+showLitChar :: Char -> ShowS
+showLitChar c s | c > '\DEL' = showChar '\\' (protectEsc isDigit (shows (ord c)) s)
+showLitChar '\DEL' s = showString "\\DEL" s
+showLitChar '\\' s = showString "\\\\" s
+showLitChar c s | c >= ' ' = showChar c s
+showLitChar '\a' s = showString "\\a" s
+showLitChar '\b' s = showString "\\b" s
+showLitChar '\f' s = showString "\\f" s
+showLitChar '\n' s = showString "\\n" s
+showLitChar '\r' s = showString "\\r" s
+showLitChar '\t' s = showString "\\t" s
+showLitChar '\v' s = showString "\\v" s
+showLitChar '\SO' s = protectEsc (== 'H') (showString "\\SO") s
+showLitChar c s = showString ('\\' : asciiTab!!ord c) s
+ -- I've done manual eta-expansion here, becuase otherwise it's
+ -- impossible to stop (asciiTab!!ord) getting floated out as an MFE
+
+protectEsc :: (Char -> Bool) -> ShowS -> ShowS
+protectEsc p f = f . cont
+ where cont s@(c:_) | p c = "\\&" ++ s
+ cont s = s
+
+intToDigit :: Int -> Char
+intToDigit (I# i)
+ | i >=# 0# && i <=# 9# = unsafeChr (ord '0' `plusInt` I# i)
+ | i >=# 10# && i <=# 15# = unsafeChr (ord 'a' `minusInt` I# 10# `plusInt` I# i)
+ | otherwise = error ("Char.intToDigit: not a digit " ++ show (I# i))
+
+\end{code}
+
+Code specific for Ints.
+
+\begin{code}
+showSignedInt :: Int -> Int -> ShowS
+showSignedInt (I# p) (I# n) r
+ | n <# 0# && p ># 6# = '(' : itos n (')' : r)
+ | otherwise = itos n r
+
+itos :: Int# -> String -> String
+itos n# cs
+ | n# <# 0# = let
+ n'# = negateInt# n#
+ in if n'# <# 0# -- minInt?
+ then '-' : itos' (negateInt# (n'# `quotInt#` 10#))
+ (itos' (negateInt# (n'# `remInt#` 10#)) cs)
+ else '-' : itos' n'# cs
+ | otherwise = itos' n# cs
+ where
+ itos' :: Int# -> String -> String
+ itos' n# cs
+ | n# <# 10# = C# (chr# (ord# '0'# +# n#)) : cs
+ | otherwise = itos' (n# `quotInt#` 10#)
+ (C# (chr# (ord# '0'# +# (n# `remInt#` 10#))) : cs)
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Character stuff}
+%* *
+%*********************************************************
+
+\begin{code}
+isAscii, isLatin1, isControl, isPrint, isSpace, isUpper,
+ isLower, isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum,
+ isAsciiUpper, isAsciiLower :: Char -> Bool
+isAscii c = c < '\x80'
+isLatin1 c = c <= '\xff'
+isControl c = c < ' ' || c >= '\DEL' && c <= '\x9f'
+isPrint c = not (isControl c)
+
+-- isSpace includes non-breaking space
+-- Done with explicit equalities both for efficiency, and to avoid a tiresome
+-- recursion with GHC.List elem
+isSpace c = c == ' ' ||
+ c == '\t' ||
+ c == '\n' ||
+ c == '\r' ||
+ c == '\f' ||
+ c == '\v' ||
+ c == '\xa0'
+
+-- The upper case ISO characters have the multiplication sign dumped
+-- randomly in the middle of the range. Go figure.
+isUpper c = c >= 'A' && c <= 'Z' ||
+ c >= '\xC0' && c <= '\xD6' ||
+ c >= '\xD8' && c <= '\xDE'
+-- The lower case ISO characters have the division sign dumped
+-- randomly in the middle of the range. Go figure.
+isLower c = c >= 'a' && c <= 'z' ||
+ c >= '\xDF' && c <= '\xF6' ||
+ c >= '\xF8' && c <= '\xFF'
+isAsciiLower c = c >= 'a' && c <= 'z'
+isAsciiUpper c = c >= 'A' && c <= 'Z'
+
+isAlpha c = isLower c || isUpper c
+isDigit c = c >= '0' && c <= '9'
+isOctDigit c = c >= '0' && c <= '7'
+isHexDigit c = isDigit c || c >= 'A' && c <= 'F' ||
+ c >= 'a' && c <= 'f'
+isAlphaNum c = isAlpha c || isDigit c
+
+-- Case-changing operations
+
+toUpper, toLower :: Char -> Char
+toUpper c@(C# c#)
+ | isAsciiLower c = C# (chr# (ord# c# -# 32#))
+ | isAscii c = c
+ -- fall-through to the slower stuff.
+ | isLower c && c /= '\xDF' && c /= '\xFF'
+ = unsafeChr (ord c `minusInt` ord 'a' `plusInt` ord 'A')
+ | otherwise
+ = c
+
+
+
+toLower c@(C# c#)
+ | isAsciiUpper c = C# (chr# (ord# c# +# 32#))
+ | isAscii c = c
+ | isUpper c = unsafeChr (ord c `minusInt` ord 'A' `plusInt` ord 'a')
+ | otherwise = c
+
+asciiTab :: [String]
+asciiTab = -- Using an array drags in the array module. listArray ('\NUL', ' ')
+ ["NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
+ "SP"]
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Functions on strings}
+%* *
+%*********************************************************
+
+lines breaks a string up into a list of strings at newline characters.
+The resulting strings do not contain newlines. Similary, words
+breaks a string up into a list of words, which were delimited by
+white space. unlines and unwords are the inverse operations.
+unlines joins lines with terminating newlines, and unwords joins
+words with separating spaces.
+
+\begin{code}
+lines :: String -> [String]
+lines "" = []
+lines s = let (l, s') = break (== '\n') s
+ in l : case s' of
+ [] -> []
+ (_:s'') -> lines s''
+
+words :: String -> [String]
+words s = case dropWhile {-partain:Char.-}isSpace s of
+ "" -> []
+ s' -> w : words s''
+ where (w, s'') =
+ break {-partain:Char.-}isSpace s'
+
+unlines :: [String] -> String
+#ifdef USE_REPORT_PRELUDE
+unlines = concatMap (++ "\n")
+#else
+-- HBC version (stolen)
+-- here's a more efficient version
+unlines [] = []
+unlines (l:ls) = l ++ '\n' : unlines ls
+#endif
+
+unwords :: [String] -> String
+#ifdef USE_REPORT_PRELUDE
+unwords [] = ""
+unwords ws = foldr1 (\w s -> w ++ ' ':s) ws
+#else
+-- HBC version (stolen)
+-- here's a more efficient version
+unwords [] = ""
+unwords [w] = w
+unwords (w:ws) = w ++ ' ' : unwords ws
+#endif
+
+\end{code}
diff --git a/libraries/base/GHC/Stable.lhs b/libraries/base/GHC/Stable.lhs
new file mode 100644
index 0000000000..691fe6c52f
--- /dev/null
+++ b/libraries/base/GHC/Stable.lhs
@@ -0,0 +1,54 @@
+% -----------------------------------------------------------------------------
+% $Id: Stable.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The GHC Team, 1992-2000
+%
+
+\section{Module @GHC.Stable@}
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Stable
+ ( StablePtr(..)
+ , newStablePtr -- :: a -> IO (StablePtr a)
+ , deRefStablePtr -- :: StablePtr a -> a
+ , freeStablePtr -- :: StablePtr a -> IO ()
+ , castStablePtrToPtr -- :: StablePtr a -> Ptr ()
+ , castPtrToStablePtr -- :: Ptr () -> StablePtr a
+ ) where
+
+import Foreign.Ptr
+
+import GHC.Base
+import GHC.IOBase
+
+-----------------------------------------------------------------------------
+-- Stable Pointers
+
+data StablePtr a = StablePtr (StablePtr# a)
+
+instance CCallable (StablePtr a)
+instance CReturnable (StablePtr a)
+
+newStablePtr :: a -> IO (StablePtr a)
+newStablePtr a = IO $ \ s ->
+ case makeStablePtr# a s of (# s', sp #) -> (# s', StablePtr sp #)
+
+deRefStablePtr :: StablePtr a -> IO a
+deRefStablePtr (StablePtr sp) = IO $ \s -> deRefStablePtr# sp s
+
+foreign import unsafe freeStablePtr :: StablePtr a -> IO ()
+
+castStablePtrToPtr :: StablePtr a -> Ptr ()
+castStablePtrToPtr (StablePtr s) = Ptr (unsafeCoerce# s)
+
+castPtrToStablePtr :: Ptr () -> StablePtr a
+castPtrToStablePtr (Ptr a) = StablePtr (unsafeCoerce# a)
+
+instance Eq (StablePtr a) where
+ (StablePtr sp1) == (StablePtr sp2) =
+ case eqStablePtr# sp1 sp2 of
+ 0# -> False
+ _ -> True
+\end{code}
diff --git a/libraries/base/GHC/Storable.lhs b/libraries/base/GHC/Storable.lhs
new file mode 100644
index 0000000000..e340a8ee88
--- /dev/null
+++ b/libraries/base/GHC/Storable.lhs
@@ -0,0 +1,289 @@
+% -----------------------------------------------------------------------------
+% $Id: Storable.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The FFI task force, 2000
+%
+
+A class for primitive marshaling
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude -monly-3-regs #-}
+
+#include "MachDeps.h"
+
+module GHC.Storable
+ ( Storable(
+ sizeOf, -- :: a -> Int
+ alignment, -- :: a -> Int
+ peekElemOff, -- :: Ptr a -> Int -> IO a
+ pokeElemOff, -- :: Ptr a -> Int -> a -> IO ()
+ peekByteOff, -- :: Ptr b -> Int -> IO a
+ pokeByteOff, -- :: Ptr b -> Int -> a -> IO ()
+ peek, -- :: Ptr a -> IO a
+ poke, -- :: Ptr a -> a -> IO ()
+ destruct) -- :: Ptr a -> IO ()
+ ) where
+\end{code}
+
+\begin{code}
+import Control.Monad ( liftM )
+import Foreign.C.Types
+import Foreign.C.TypesISO
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Stable ( StablePtr )
+import GHC.Num
+import GHC.Int
+import GHC.Word
+import GHC.Stable
+import Foreign.Ptr
+import GHC.Float
+import GHC.Err
+import GHC.IOBase
+import GHC.Base
+#endif
+\end{code}
+
+Primitive marshaling
+
+Minimal complete definition: sizeOf, alignment, and one definition
+in each of the peek/poke families.
+
+\begin{code}
+class Storable a where
+
+ -- sizeOf/alignment *never* use their first argument
+ sizeOf :: a -> Int
+ alignment :: a -> Int
+
+ -- replacement for read-/write???OffAddr
+ peekElemOff :: Ptr a -> Int -> IO a
+ pokeElemOff :: Ptr a -> Int -> a -> IO ()
+
+ -- the same with *byte* offsets
+ peekByteOff :: Ptr b -> Int -> IO a
+ pokeByteOff :: Ptr b -> Int -> a -> IO ()
+
+ -- ... and with no offsets at all
+ peek :: Ptr a -> IO a
+ poke :: Ptr a -> a -> IO ()
+
+ -- free memory associated with the object
+ -- (except the object pointer itself)
+ destruct :: Ptr a -> IO ()
+
+ -- circular default instances
+ peekElemOff = peekElemOff_ undefined
+ where peekElemOff_ :: a -> Ptr a -> Int -> IO a
+ peekElemOff_ undef ptr off = peekByteOff ptr (off * sizeOf undef)
+ pokeElemOff ptr off val = pokeByteOff ptr (off * sizeOf val) val
+
+ peekByteOff ptr off = peek (ptr `plusPtr` off)
+ pokeByteOff ptr off = poke (ptr `plusPtr` off)
+
+ peek ptr = peekElemOff ptr 0
+ poke ptr = pokeElemOff ptr 0
+
+ destruct _ = return ()
+\end{code}
+
+System-dependent, but rather obvious instances
+
+\begin{code}
+instance Storable Bool where
+ sizeOf _ = sizeOf (undefined::CInt)
+ alignment _ = alignment (undefined::CInt)
+ peekElemOff p i = liftM (/= (0::CInt)) $ peekElemOff (castPtr p) i
+ pokeElemOff p i x = pokeElemOff (castPtr p) i (if x then 1 else 0::CInt)
+
+#define STORABLE(T,size,align,read,write) \
+instance Storable (T) where { \
+ sizeOf _ = size; \
+ alignment _ = align; \
+ peekElemOff = read; \
+ pokeElemOff = write }
+
+STORABLE(Char,SIZEOF_INT32,ALIGNMENT_INT32,
+ readWideCharOffPtr,writeWideCharOffPtr)
+
+STORABLE(Int,SIZEOF_LONG,ALIGNMENT_LONG,
+ readIntOffPtr,writeIntOffPtr)
+
+STORABLE(Word,SIZEOF_LONG,ALIGNMENT_LONG,
+ readWordOffPtr,writeWordOffPtr)
+
+STORABLE((Ptr a),SIZEOF_VOID_P,ALIGNMENT_VOID_P,
+ readPtrOffPtr,writePtrOffPtr)
+
+STORABLE((FunPtr a),SIZEOF_VOID_P,ALIGNMENT_VOID_P,
+ readFunPtrOffPtr,writeFunPtrOffPtr)
+
+STORABLE((StablePtr a),SIZEOF_VOID_P,ALIGNMENT_VOID_P,
+ readStablePtrOffPtr,writeStablePtrOffPtr)
+
+STORABLE(Float,SIZEOF_FLOAT,ALIGNMENT_FLOAT,
+ readFloatOffPtr,writeFloatOffPtr)
+
+STORABLE(Double,SIZEOF_DOUBLE,ALIGNMENT_DOUBLE,
+ readDoubleOffPtr,writeDoubleOffPtr)
+
+STORABLE(Word8,SIZEOF_WORD8,ALIGNMENT_WORD8,
+ readWord8OffPtr,writeWord8OffPtr)
+
+STORABLE(Word16,SIZEOF_WORD16,ALIGNMENT_WORD16,
+ readWord16OffPtr,writeWord16OffPtr)
+
+STORABLE(Word32,SIZEOF_WORD32,ALIGNMENT_WORD32,
+ readWord32OffPtr,writeWord32OffPtr)
+
+STORABLE(Word64,SIZEOF_WORD64,ALIGNMENT_WORD64,
+ readWord64OffPtr,writeWord64OffPtr)
+
+STORABLE(Int8,SIZEOF_INT8,ALIGNMENT_INT8,
+ readInt8OffPtr,writeInt8OffPtr)
+
+STORABLE(Int16,SIZEOF_INT16,ALIGNMENT_INT16,
+ readInt16OffPtr,writeInt16OffPtr)
+
+STORABLE(Int32,SIZEOF_INT32,ALIGNMENT_INT32,
+ readInt32OffPtr,writeInt32OffPtr)
+
+STORABLE(Int64,SIZEOF_INT64,ALIGNMENT_INT64,
+ readInt64OffPtr,writeInt64OffPtr)
+
+#define NSTORABLE(T) \
+instance Storable T where { \
+ sizeOf (T x) = sizeOf x ; \
+ alignment (T x) = alignment x ; \
+ peekElemOff a i = liftM T (peekElemOff (castPtr a) i) ; \
+ pokeElemOff a i (T x) = pokeElemOff (castPtr a) i x }
+
+NSTORABLE(CChar)
+NSTORABLE(CSChar)
+NSTORABLE(CUChar)
+NSTORABLE(CShort)
+NSTORABLE(CUShort)
+NSTORABLE(CInt)
+NSTORABLE(CUInt)
+NSTORABLE(CLong)
+NSTORABLE(CULong)
+NSTORABLE(CLLong)
+NSTORABLE(CULLong)
+NSTORABLE(CFloat)
+NSTORABLE(CDouble)
+NSTORABLE(CLDouble)
+NSTORABLE(CPtrdiff)
+NSTORABLE(CSize)
+NSTORABLE(CWchar)
+NSTORABLE(CSigAtomic)
+NSTORABLE(CClock)
+NSTORABLE(CTime)
+\end{code}
+
+Helper functions
+
+\begin{code}
+#ifdef __GLASGOW_HASKELL__
+
+readWideCharOffPtr :: Ptr Char -> Int -> IO Char
+readIntOffPtr :: Ptr Int -> Int -> IO Int
+readWordOffPtr :: Ptr Word -> Int -> IO Word
+readPtrOffPtr :: Ptr (Ptr a) -> Int -> IO (Ptr a)
+readFunPtrOffPtr :: Ptr (FunPtr a) -> Int -> IO (FunPtr a)
+readFloatOffPtr :: Ptr Float -> Int -> IO Float
+readDoubleOffPtr :: Ptr Double -> Int -> IO Double
+readStablePtrOffPtr :: Ptr (StablePtr a) -> Int -> IO (StablePtr a)
+readInt8OffPtr :: Ptr Int8 -> Int -> IO Int8
+readInt16OffPtr :: Ptr Int16 -> Int -> IO Int16
+readInt32OffPtr :: Ptr Int32 -> Int -> IO Int32
+readInt64OffPtr :: Ptr Int64 -> Int -> IO Int64
+readWord8OffPtr :: Ptr Word8 -> Int -> IO Word8
+readWord16OffPtr :: Ptr Word16 -> Int -> IO Word16
+readWord32OffPtr :: Ptr Word32 -> Int -> IO Word32
+readWord64OffPtr :: Ptr Word64 -> Int -> IO Word64
+
+readWideCharOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readWideCharOffAddr# a i s of (# s2, x #) -> (# s2, C# x #)
+readIntOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readIntOffAddr# a i s of (# s2, x #) -> (# s2, I# x #)
+readWordOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readWordOffAddr# a i s of (# s2, x #) -> (# s2, W# x #)
+readPtrOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readAddrOffAddr# a i s of (# s2, x #) -> (# s2, Ptr x #)
+readFunPtrOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readAddrOffAddr# a i s of (# s2, x #) -> (# s2, FunPtr x #)
+readFloatOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readFloatOffAddr# a i s of (# s2, x #) -> (# s2, F# x #)
+readDoubleOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readDoubleOffAddr# a i s of (# s2, x #) -> (# s2, D# x #)
+readStablePtrOffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readStablePtrOffAddr# a i s of (# s2, x #) -> (# s2, StablePtr x #)
+readInt8OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readInt8OffAddr# a i s of (# s2, x #) -> (# s2, I8# x #)
+readInt16OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readInt16OffAddr# a i s of (# s2, x #) -> (# s2, I16# x #)
+readInt32OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readInt32OffAddr# a i s of (# s2, x #) -> (# s2, I32# x #)
+readInt64OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readInt64OffAddr# a i s of (# s2, x #) -> (# s2, I64# x #)
+readWord8OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readWord8OffAddr# a i s of (# s2, x #) -> (# s2, W8# x #)
+readWord16OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readWord16OffAddr# a i s of (# s2, x #) -> (# s2, W16# x #)
+readWord32OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readWord32OffAddr# a i s of (# s2, x #) -> (# s2, W32# x #)
+readWord64OffPtr (Ptr a) (I# i)
+ = IO $ \s -> case readWord64OffAddr# a i s of (# s2, x #) -> (# s2, W64# x #)
+
+writeWideCharOffPtr :: Ptr Char -> Int -> Char -> IO ()
+writeIntOffPtr :: Ptr Int -> Int -> Int -> IO ()
+writeWordOffPtr :: Ptr Word -> Int -> Word -> IO ()
+writePtrOffPtr :: Ptr (Ptr a) -> Int -> Ptr a -> IO ()
+writeFunPtrOffPtr :: Ptr (FunPtr a) -> Int -> FunPtr a -> IO ()
+writeFloatOffPtr :: Ptr Float -> Int -> Float -> IO ()
+writeDoubleOffPtr :: Ptr Double -> Int -> Double -> IO ()
+writeStablePtrOffPtr :: Ptr (StablePtr a) -> Int -> StablePtr a -> IO ()
+writeInt8OffPtr :: Ptr Int8 -> Int -> Int8 -> IO ()
+writeInt16OffPtr :: Ptr Int16 -> Int -> Int16 -> IO ()
+writeInt32OffPtr :: Ptr Int32 -> Int -> Int32 -> IO ()
+writeInt64OffPtr :: Ptr Int64 -> Int -> Int64 -> IO ()
+writeWord8OffPtr :: Ptr Word8 -> Int -> Word8 -> IO ()
+writeWord16OffPtr :: Ptr Word16 -> Int -> Word16 -> IO ()
+writeWord32OffPtr :: Ptr Word32 -> Int -> Word32 -> IO ()
+writeWord64OffPtr :: Ptr Word64 -> Int -> Word64 -> IO ()
+
+writeWideCharOffPtr (Ptr a) (I# i) (C# x)
+ = IO $ \s -> case writeWideCharOffAddr# a i x s of s2 -> (# s2, () #)
+writeIntOffPtr (Ptr a) (I# i) (I# x)
+ = IO $ \s -> case writeIntOffAddr# a i x s of s2 -> (# s2, () #)
+writeWordOffPtr (Ptr a) (I# i) (W# x)
+ = IO $ \s -> case writeWordOffAddr# a i x s of s2 -> (# s2, () #)
+writePtrOffPtr (Ptr a) (I# i) (Ptr x)
+ = IO $ \s -> case writeAddrOffAddr# a i x s of s2 -> (# s2, () #)
+writeFunPtrOffPtr (Ptr a) (I# i) (FunPtr x)
+ = IO $ \s -> case writeAddrOffAddr# a i x s of s2 -> (# s2, () #)
+writeFloatOffPtr (Ptr a) (I# i) (F# x)
+ = IO $ \s -> case writeFloatOffAddr# a i x s of s2 -> (# s2, () #)
+writeDoubleOffPtr (Ptr a) (I# i) (D# x)
+ = IO $ \s -> case writeDoubleOffAddr# a i x s of s2 -> (# s2, () #)
+writeStablePtrOffPtr (Ptr a) (I# i) (StablePtr x)
+ = IO $ \s -> case writeStablePtrOffAddr# a i x s of s2 -> (# s2 , () #)
+writeInt8OffPtr (Ptr a) (I# i) (I8# x)
+ = IO $ \s -> case writeInt8OffAddr# a i x s of s2 -> (# s2, () #)
+writeInt16OffPtr (Ptr a) (I# i) (I16# x)
+ = IO $ \s -> case writeInt16OffAddr# a i x s of s2 -> (# s2, () #)
+writeInt32OffPtr (Ptr a) (I# i) (I32# x)
+ = IO $ \s -> case writeInt32OffAddr# a i x s of s2 -> (# s2, () #)
+writeInt64OffPtr (Ptr a) (I# i) (I64# x)
+ = IO $ \s -> case writeInt64OffAddr# a i x s of s2 -> (# s2, () #)
+writeWord8OffPtr (Ptr a) (I# i) (W8# x)
+ = IO $ \s -> case writeWord8OffAddr# a i x s of s2 -> (# s2, () #)
+writeWord16OffPtr (Ptr a) (I# i) (W16# x)
+ = IO $ \s -> case writeWord16OffAddr# a i x s of s2 -> (# s2, () #)
+writeWord32OffPtr (Ptr a) (I# i) (W32# x)
+ = IO $ \s -> case writeWord32OffAddr# a i x s of s2 -> (# s2, () #)
+writeWord64OffPtr (Ptr a) (I# i) (W64# x)
+ = IO $ \s -> case writeWord64OffAddr# a i x s of s2 -> (# s2, () #)
+
+#endif /* __GLASGOW_HASKELL__ */
+\end{code}
diff --git a/libraries/base/GHC/TopHandler.lhs b/libraries/base/GHC/TopHandler.lhs
new file mode 100644
index 0000000000..18e807ae3c
--- /dev/null
+++ b/libraries/base/GHC/TopHandler.lhs
@@ -0,0 +1,85 @@
+-- -----------------------------------------------------------------------------
+-- $Id: TopHandler.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+--
+-- (c) The University of Glasgow, 2001
+--
+-- GHC.TopHandler
+--
+-- 'Top-level' IO actions want to catch exceptions (e.g., forkIO and
+-- GHC.Main.mainIO) and report them - topHandler is the exception
+-- handler they should use for this:
+
+-- make sure we handle errors while reporting the error!
+-- (e.g. evaluating the string passed to 'error' might generate
+-- another error, etc.)
+
+-- These functions can't go in GHC.Main, because GHC.Main isn't
+-- included in HSstd.o (because GHC.Main depends on Main, which
+-- doesn't exist yet...).
+
+\begin{code}
+module GHC.TopHandler (
+ topHandler, reportStackOverflow, reportError
+ ) where
+
+import Prelude
+
+import System.IO
+
+import Foreign.C.String
+import Foreign.Ptr
+import GHC.IOBase
+import GHC.Exception
+
+topHandler :: Exception -> IO ()
+topHandler err = catchException (real_handler err) topHandler
+
+real_handler :: Exception -> IO ()
+real_handler ex =
+ case ex of
+ AsyncException StackOverflow -> reportStackOverflow True
+
+ -- only the main thread gets ExitException exceptions
+ ExitException ExitSuccess -> shutdownHaskellAndExit 0
+ ExitException (ExitFailure n) -> shutdownHaskellAndExit n
+
+ ErrorCall s -> reportError True s
+ other -> reportError True (showsPrec 0 other "\n")
+
+-- NOTE: shutdownHaskellAndExit must be called "safe", because it *can*
+-- re-enter Haskell land through finalizers.
+foreign import ccall "shutdownHaskellAndExit"
+ shutdownHaskellAndExit :: Int -> IO ()
+
+reportStackOverflow :: Bool -> IO ()
+reportStackOverflow bombOut = do
+ (hFlush stdout) `catchException` (\ _ -> return ())
+ callStackOverflowHook
+ if bombOut then
+ stg_exit 2
+ else
+ return ()
+
+reportError :: Bool -> String -> IO ()
+reportError bombOut str = do
+ (hFlush stdout) `catchException` (\ _ -> return ())
+ withCStringLen str $ \(cstr,len) -> do
+ writeErrString addrOf_ErrorHdrHook cstr len
+ if bombOut
+ then stg_exit 1
+ else return ()
+
+foreign import ccall "addrOf_ErrorHdrHook" unsafe
+ addrOf_ErrorHdrHook :: Ptr ()
+
+foreign import ccall "writeErrString__" unsafe
+ writeErrString :: Ptr () -> CString -> Int -> IO ()
+
+-- SUP: Are the hooks allowed to re-enter Haskell land? If so, remove
+-- the unsafe below.
+foreign import ccall "stackOverflow" unsafe
+ callStackOverflowHook :: IO ()
+
+foreign import ccall "stg_exit" unsafe
+ stg_exit :: Int -> IO ()
+\end{code}
diff --git a/libraries/base/GHC/Tup.lhs b/libraries/base/GHC/Tup.lhs
new file mode 100644
index 0000000000..5e3de77f89
--- /dev/null
+++ b/libraries/base/GHC/Tup.lhs
@@ -0,0 +1,238 @@
+% -----------------------------------------------------------------------------
+% $Id: Tup.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1992-2000
+%
+
+\section[GHC.Tup]{Module @GHC.Tup@}
+
+This modules defines the typle data types.
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Tup where
+
+import GHC.Base
+
+default () -- Double isn't available yet
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Other tuple types}
+%* *
+%*********************************************************
+
+\begin{code}
+data (,) a b = (,) a b deriving (Eq, Ord)
+data (,,) a b c = (,,) a b c deriving (Eq, Ord)
+data (,,,) a b c d = (,,,) a b c d deriving (Eq, Ord)
+data (,,,,) a b c d e = (,,,,) a b c d e deriving (Eq, Ord)
+data (,,,,,) a b c d e f = (,,,,,) a b c d e f
+data (,,,,,,) a b c d e f g = (,,,,,,) a b c d e f g
+data (,,,,,,,) a b c d e f g h = (,,,,,,,) a b c d e f g h
+data (,,,,,,,,) a b c d e f g h i = (,,,,,,,,) a b c d e f g h i
+data (,,,,,,,,,) a b c d e f g h i j = (,,,,,,,,,) a b c d e f g h i j
+data (,,,,,,,,,,) a b c d e f g h i j k = (,,,,,,,,,,) a b c d e f g h i j k
+data (,,,,,,,,,,,) a b c d e f g h i j k l = (,,,,,,,,,,,) a b c d e f g h i j k l
+data (,,,,,,,,,,,,) a b c d e f g h i j k l m = (,,,,,,,,,,,,) a b c d e f g h i j k l m
+data (,,,,,,,,,,,,,) a b c d e f g h i j k l m n = (,,,,,,,,,,,,,) a b c d e f g h i j k l m n
+data (,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o = (,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o
+data (,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p = (,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p
+data (,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q
+ = (,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q
+data (,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r
+ = (,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r
+data (,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s
+ = (,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s
+data (,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t
+ = (,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t
+data (,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u
+ = (,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u
+data (,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v
+ = (,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v
+data (,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w
+ = (,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w
+data (,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x
+ = (,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x
+data (,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y
+ = (,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y
+data (,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__
+{- Manuel says: Including one more declaration gives a segmentation fault.
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___ t___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___ t___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___ t___ u___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___ t___ u___
+data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___ t___ u___ v___
+ = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__ k__ l__ m__ n__ o__ p__ q__ r__ s__ t__ u__ v__ w__ x__ y__ z__ a___ b___ c___ d___ e___ f___ g___ h___ i___ j___ k___ l___ m___ n___ o___ p___ q___ r___ s___ t___ u___ v___
+-}
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Standard functions over tuples}
+* *
+%*********************************************************
+
+\begin{code}
+fst :: (a,b) -> a
+fst (x,_) = x
+
+snd :: (a,b) -> b
+snd (_,y) = y
+
+-- curry converts an uncurried function to a curried function;
+-- uncurry converts a curried function to a function on pairs.
+curry :: ((a, b) -> c) -> a -> b -> c
+curry f x y = f (x, y)
+
+uncurry :: (a -> b -> c) -> ((a, b) -> c)
+uncurry f p = f (fst p) (snd p)
+\end{code}
+
diff --git a/libraries/base/GHC/Weak.lhs b/libraries/base/GHC/Weak.lhs
new file mode 100644
index 0000000000..b9e5172bf0
--- /dev/null
+++ b/libraries/base/GHC/Weak.lhs
@@ -0,0 +1,65 @@
+% ------------------------------------------------------------------------------
+% $Id: Weak.lhs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
+%
+% (c) The University of Glasgow, 1998-2000
+%
+
+\section[GHC.Weak]{Module @GHC.Weak@}
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module GHC.Weak where
+
+import GHC.Prim
+import GHC.Base
+import GHC.Maybe
+import GHC.IOBase ( IO(..), unIO )
+
+data Weak v = Weak (Weak# v)
+
+mkWeak :: k -- key
+ -> v -- value
+ -> Maybe (IO ()) -- finalizer
+ -> IO (Weak v) -- weak pointer
+
+mkWeak key val (Just finalizer) = IO $ \s ->
+ case mkWeak# key val finalizer s of { (# s1, w #) -> (# s1, Weak w #) }
+mkWeak key val Nothing = IO $ \s ->
+ case mkWeak# key val (unsafeCoerce# 0#) s of { (# s1, w #) -> (# s1, Weak w #) }
+
+mkWeakPtr :: k -> Maybe (IO ()) -> IO (Weak k)
+mkWeakPtr key finalizer = mkWeak key key finalizer
+
+addFinalizer :: key -> IO () -> IO ()
+addFinalizer key finalizer = do
+ mkWeakPtr key (Just finalizer) -- throw it away
+ return ()
+
+{-
+Instance Eq (Weak v) where
+ (Weak w1) == (Weak w2) = w1 `sameWeak#` w2
+-}
+
+
+-- run a batch of finalizers from the garbage collector. We're given
+-- an array of finalizers and the length of the array, and we just
+-- call each one in turn.
+--
+-- the IO primitives are inlined by hand here to get the optimal
+-- code (sigh) --SDM.
+
+runFinalizerBatch :: Int -> Array# (IO ()) -> IO ()
+runFinalizerBatch (I# n) arr =
+ let go m = IO $ \s ->
+ case m of
+ 0# -> (# s, () #)
+ _ -> let m' = m -# 1# in
+ case indexArray# arr m' of { (# io #) ->
+ case unIO io s of { (# s, _ #) ->
+ unIO (go m') s
+ }}
+ in
+ go n
+
+\end{code}
diff --git a/libraries/base/GHC/Word.lhs b/libraries/base/GHC/Word.lhs
new file mode 100644
index 0000000000..fe847fc3fd
--- /dev/null
+++ b/libraries/base/GHC/Word.lhs
@@ -0,0 +1,737 @@
+%
+% (c) The University of Glasgow, 1997-2001
+%
+\section[GHC.Word]{Module @GHC.Word@}
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+#include "MachDeps.h"
+
+module GHC.Word (
+ Word(..), Word8(..), Word16(..), Word32(..), Word64(..),
+ divZeroError, toEnumError, fromEnumError, succError, predError)
+ where
+
+import Data.Bits
+
+import GHC.Base
+import GHC.Enum
+import GHC.Num
+import GHC.Real
+import GHC.Read
+import GHC.Arr
+import GHC.Show
+
+------------------------------------------------------------------------
+-- Helper functions
+------------------------------------------------------------------------
+
+{-# NOINLINE divZeroError #-}
+divZeroError :: (Show a) => String -> a -> b
+divZeroError meth x =
+ error $ "Integral." ++ meth ++ ": divide by 0 (" ++ show x ++ " / 0)"
+
+{-# NOINLINE toEnumError #-}
+toEnumError :: (Show a) => String -> Int -> (a,a) -> b
+toEnumError inst_ty i bnds =
+ error $ "Enum.toEnum{" ++ inst_ty ++ "}: tag (" ++
+ show i ++
+ ") is outside of bounds " ++
+ show bnds
+
+{-# NOINLINE fromEnumError #-}
+fromEnumError :: (Show a) => String -> a -> b
+fromEnumError inst_ty x =
+ error $ "Enum.fromEnum{" ++ inst_ty ++ "}: value (" ++
+ show x ++
+ ") is outside of Int's bounds " ++
+ show (minBound::Int, maxBound::Int)
+
+{-# NOINLINE succError #-}
+succError :: String -> a
+succError inst_ty =
+ error $ "Enum.succ{" ++ inst_ty ++ "}: tried to take `succ' of maxBound"
+
+{-# NOINLINE predError #-}
+predError :: String -> a
+predError inst_ty =
+ error $ "Enum.pred{" ++ inst_ty ++ "}: tried to take `pred' of minBound"
+
+------------------------------------------------------------------------
+-- type Word
+------------------------------------------------------------------------
+
+-- A Word is an unsigned integral type, with the same size as Int.
+
+data Word = W# Word# deriving (Eq, Ord)
+
+instance CCallable Word
+instance CReturnable Word
+
+instance Show Word where
+ showsPrec p x = showsPrec p (toInteger x)
+
+instance Num Word where
+ (W# x#) + (W# y#) = W# (x# `plusWord#` y#)
+ (W# x#) - (W# y#) = W# (x# `minusWord#` y#)
+ (W# x#) * (W# y#) = W# (x# `timesWord#` y#)
+ negate (W# x#) = W# (int2Word# (negateInt# (word2Int# x#)))
+ abs x = x
+ signum 0 = 0
+ signum _ = 1
+ fromInteger (S# i#) = W# (int2Word# i#)
+ fromInteger (J# s# d#) = W# (integer2Word# s# d#)
+
+instance Real Word where
+ toRational x = toInteger x % 1
+
+instance Enum Word where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Word"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Word"
+ toEnum i@(I# i#)
+ | i >= 0 = W# (int2Word# i#)
+ | otherwise = toEnumError "Word" i (minBound::Word, maxBound::Word)
+ fromEnum x@(W# x#)
+ | x <= fromIntegral (maxBound::Int)
+ = I# (word2Int# x#)
+ | otherwise = fromEnumError "Word" x
+ enumFrom = integralEnumFrom
+ enumFromThen = integralEnumFromThen
+ enumFromTo = integralEnumFromTo
+ enumFromThenTo = integralEnumFromThenTo
+
+instance Integral Word where
+ quot x@(W# x#) y@(W# y#)
+ | y /= 0 = W# (x# `quotWord#` y#)
+ | otherwise = divZeroError "quot{Word}" x
+ rem x@(W# x#) y@(W# y#)
+ | y /= 0 = W# (x# `remWord#` y#)
+ | otherwise = divZeroError "rem{Word}" x
+ div x@(W# x#) y@(W# y#)
+ | y /= 0 = W# (x# `quotWord#` y#)
+ | otherwise = divZeroError "div{Word}" x
+ mod x@(W# x#) y@(W# y#)
+ | y /= 0 = W# (x# `remWord#` y#)
+ | otherwise = divZeroError "mod{Word}" x
+ quotRem x@(W# x#) y@(W# y#)
+ | y /= 0 = (W# (x# `quotWord#` y#), W# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word}" x
+ divMod x@(W# x#) y@(W# y#)
+ | y /= 0 = (W# (x# `quotWord#` y#), W# (x# `remWord#` y#))
+ | otherwise = divZeroError "divMod{Word}" x
+ toInteger (W# x#)
+ | i# >=# 0# = S# i#
+ | otherwise = case word2Integer# x# of (# s, d #) -> J# s d
+ where
+ i# = word2Int# x#
+
+instance Bounded Word where
+ minBound = 0
+#if WORD_SIZE_IN_BYTES == 4
+ maxBound = 0xFFFFFFFF
+#else
+ maxBound = 0xFFFFFFFFFFFFFFFF
+#endif
+
+instance Ix Word where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Word"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Word where
+ readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]
+
+instance Bits Word where
+ (W# x#) .&. (W# y#) = W# (x# `and#` y#)
+ (W# x#) .|. (W# y#) = W# (x# `or#` y#)
+ (W# x#) `xor` (W# y#) = W# (x# `xor#` y#)
+ complement (W# x#) = W# (x# `xor#` mb#) where W# mb# = maxBound
+ (W# x#) `shift` (I# i#)
+ | i# >=# 0# = W# (x# `shiftL#` i#)
+ | otherwise = W# (x# `shiftRL#` negateInt# i#)
+#if WORD_SIZE_IN_BYTES == 4
+ (W# x#) `rotate` (I# i#) = W# ((x# `shiftL#` i'#) `or#` (x# `shiftRL#` (32# -# i'#)))
+ where
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 31#)
+#else
+ (W# x#) `rotate` (I# i#) = W# ((x# `shiftL#` i'#) `or#` (x# `shiftRL#` (64# -# i'#)))
+ where
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)
+#endif
+ bitSize _ = WORD_SIZE_IN_BYTES * 8
+ isSigned _ = False
+
+{-# RULES
+"fromIntegral/Int->Word" fromIntegral = \(I# x#) -> W# (int2Word# x#)
+"fromIntegral/Word->Int" fromIntegral = \(W# x#) -> I# (word2Int# x#)
+"fromIntegral/Word->Word" fromIntegral = id :: Word -> Word
+ #-}
+
+------------------------------------------------------------------------
+-- type Word8
+------------------------------------------------------------------------
+
+-- Word8 is represented in the same way as Word. Operations may assume
+-- and must ensure that it holds only values from its logical range.
+
+data Word8 = W8# Word# deriving (Eq, Ord)
+
+instance CCallable Word8
+instance CReturnable Word8
+
+instance Show Word8 where
+ showsPrec p x = showsPrec p (fromIntegral x :: Int)
+
+instance Num Word8 where
+ (W8# x#) + (W8# y#) = W8# (wordToWord8# (x# `plusWord#` y#))
+ (W8# x#) - (W8# y#) = W8# (wordToWord8# (x# `minusWord#` y#))
+ (W8# x#) * (W8# y#) = W8# (wordToWord8# (x# `timesWord#` y#))
+ negate (W8# x#) = W8# (wordToWord8# (int2Word# (negateInt# (word2Int# x#))))
+ abs x = x
+ signum 0 = 0
+ signum _ = 1
+ fromInteger (S# i#) = W8# (wordToWord8# (int2Word# i#))
+ fromInteger (J# s# d#) = W8# (wordToWord8# (integer2Word# s# d#))
+
+instance Real Word8 where
+ toRational x = toInteger x % 1
+
+instance Enum Word8 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Word8"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Word8"
+ toEnum i@(I# i#)
+ | i >= 0 && i <= fromIntegral (maxBound::Word8)
+ = W8# (int2Word# i#)
+ | otherwise = toEnumError "Word8" i (minBound::Word8, maxBound::Word8)
+ fromEnum (W8# x#) = I# (word2Int# x#)
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+
+instance Integral Word8 where
+ quot x@(W8# x#) y@(W8# y#)
+ | y /= 0 = W8# (x# `quotWord#` y#)
+ | otherwise = divZeroError "quot{Word8}" x
+ rem x@(W8# x#) y@(W8# y#)
+ | y /= 0 = W8# (x# `remWord#` y#)
+ | otherwise = divZeroError "rem{Word8}" x
+ div x@(W8# x#) y@(W8# y#)
+ | y /= 0 = W8# (x# `quotWord#` y#)
+ | otherwise = divZeroError "div{Word8}" x
+ mod x@(W8# x#) y@(W8# y#)
+ | y /= 0 = W8# (x# `remWord#` y#)
+ | otherwise = divZeroError "mod{Word8}" x
+ quotRem x@(W8# x#) y@(W8# y#)
+ | y /= 0 = (W8# (x# `quotWord#` y#), W8# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word8}" x
+ divMod x@(W8# x#) y@(W8# y#)
+ | y /= 0 = (W8# (x# `quotWord#` y#), W8# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word8}" x
+ toInteger (W8# x#) = S# (word2Int# x#)
+
+instance Bounded Word8 where
+ minBound = 0
+ maxBound = 0xFF
+
+instance Ix Word8 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Word8"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Word8 where
+ readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]
+
+instance Bits Word8 where
+ (W8# x#) .&. (W8# y#) = W8# (x# `and#` y#)
+ (W8# x#) .|. (W8# y#) = W8# (x# `or#` y#)
+ (W8# x#) `xor` (W8# y#) = W8# (x# `xor#` y#)
+ complement (W8# x#) = W8# (x# `xor#` mb#) where W8# mb# = maxBound
+ (W8# x#) `shift` (I# i#)
+ | i# >=# 0# = W8# (wordToWord8# (x# `shiftL#` i#))
+ | otherwise = W8# (x# `shiftRL#` negateInt# i#)
+ (W8# x#) `rotate` (I# i#) = W8# (wordToWord8# ((x# `shiftL#` i'#) `or#`
+ (x# `shiftRL#` (8# -# i'#))))
+ where
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 7#)
+ bitSize _ = 8
+ isSigned _ = False
+
+{-# RULES
+"fromIntegral/Word8->Word8" fromIntegral = id :: Word8 -> Word8
+"fromIntegral/Word8->Integer" fromIntegral = toInteger :: Word8 -> Integer
+"fromIntegral/a->Word8" fromIntegral = \x -> case fromIntegral x of W# x# -> W8# (wordToWord8# x#)
+"fromIntegral/Word8->a" fromIntegral = \(W8# x#) -> fromIntegral (W# x#)
+ #-}
+
+------------------------------------------------------------------------
+-- type Word16
+------------------------------------------------------------------------
+
+-- Word16 is represented in the same way as Word. Operations may assume
+-- and must ensure that it holds only values from its logical range.
+
+data Word16 = W16# Word# deriving (Eq, Ord)
+
+instance CCallable Word16
+instance CReturnable Word16
+
+instance Show Word16 where
+ showsPrec p x = showsPrec p (fromIntegral x :: Int)
+
+instance Num Word16 where
+ (W16# x#) + (W16# y#) = W16# (wordToWord16# (x# `plusWord#` y#))
+ (W16# x#) - (W16# y#) = W16# (wordToWord16# (x# `minusWord#` y#))
+ (W16# x#) * (W16# y#) = W16# (wordToWord16# (x# `timesWord#` y#))
+ negate (W16# x#) = W16# (wordToWord16# (int2Word# (negateInt# (word2Int# x#))))
+ abs x = x
+ signum 0 = 0
+ signum _ = 1
+ fromInteger (S# i#) = W16# (wordToWord16# (int2Word# i#))
+ fromInteger (J# s# d#) = W16# (wordToWord16# (integer2Word# s# d#))
+
+instance Real Word16 where
+ toRational x = toInteger x % 1
+
+instance Enum Word16 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Word16"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Word16"
+ toEnum i@(I# i#)
+ | i >= 0 && i <= fromIntegral (maxBound::Word16)
+ = W16# (int2Word# i#)
+ | otherwise = toEnumError "Word16" i (minBound::Word16, maxBound::Word16)
+ fromEnum (W16# x#) = I# (word2Int# x#)
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+
+instance Integral Word16 where
+ quot x@(W16# x#) y@(W16# y#)
+ | y /= 0 = W16# (x# `quotWord#` y#)
+ | otherwise = divZeroError "quot{Word16}" x
+ rem x@(W16# x#) y@(W16# y#)
+ | y /= 0 = W16# (x# `remWord#` y#)
+ | otherwise = divZeroError "rem{Word16}" x
+ div x@(W16# x#) y@(W16# y#)
+ | y /= 0 = W16# (x# `quotWord#` y#)
+ | otherwise = divZeroError "div{Word16}" x
+ mod x@(W16# x#) y@(W16# y#)
+ | y /= 0 = W16# (x# `remWord#` y#)
+ | otherwise = divZeroError "mod{Word16}" x
+ quotRem x@(W16# x#) y@(W16# y#)
+ | y /= 0 = (W16# (x# `quotWord#` y#), W16# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word16}" x
+ divMod x@(W16# x#) y@(W16# y#)
+ | y /= 0 = (W16# (x# `quotWord#` y#), W16# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word16}" x
+ toInteger (W16# x#) = S# (word2Int# x#)
+
+instance Bounded Word16 where
+ minBound = 0
+ maxBound = 0xFFFF
+
+instance Ix Word16 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Word16"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Word16 where
+ readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]
+
+instance Bits Word16 where
+ (W16# x#) .&. (W16# y#) = W16# (x# `and#` y#)
+ (W16# x#) .|. (W16# y#) = W16# (x# `or#` y#)
+ (W16# x#) `xor` (W16# y#) = W16# (x# `xor#` y#)
+ complement (W16# x#) = W16# (x# `xor#` mb#) where W16# mb# = maxBound
+ (W16# x#) `shift` (I# i#)
+ | i# >=# 0# = W16# (wordToWord16# (x# `shiftL#` i#))
+ | otherwise = W16# (x# `shiftRL#` negateInt# i#)
+ (W16# x#) `rotate` (I# i#) = W16# (wordToWord16# ((x# `shiftL#` i'#) `or#`
+ (x# `shiftRL#` (16# -# i'#))))
+ where
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 15#)
+ bitSize _ = 16
+ isSigned _ = False
+
+{-# RULES
+"fromIntegral/Word8->Word16" fromIntegral = \(W8# x#) -> W16# x#
+"fromIntegral/Word16->Word16" fromIntegral = id :: Word16 -> Word16
+"fromIntegral/Word16->Integer" fromIntegral = toInteger :: Word16 -> Integer
+"fromIntegral/a->Word16" fromIntegral = \x -> case fromIntegral x of W# x# -> W16# (wordToWord16# x#)
+"fromIntegral/Word16->a" fromIntegral = \(W16# x#) -> fromIntegral (W# x#)
+ #-}
+
+------------------------------------------------------------------------
+-- type Word32
+------------------------------------------------------------------------
+
+-- Word32 is represented in the same way as Word.
+#if WORD_SIZE_IN_BYTES == 8
+-- Operations may assume and must ensure that it holds only values
+-- from its logical range.
+#endif
+
+data Word32 = W32# Word# deriving (Eq, Ord)
+
+instance CCallable Word32
+instance CReturnable Word32
+
+instance Show Word32 where
+#if WORD_SIZE_IN_BYTES == 4
+ showsPrec p x = showsPrec p (toInteger x)
+#else
+ showsPrec p x = showsPrec p (fromIntegral x :: Int)
+#endif
+
+instance Num Word32 where
+ (W32# x#) + (W32# y#) = W32# (wordToWord32# (x# `plusWord#` y#))
+ (W32# x#) - (W32# y#) = W32# (wordToWord32# (x# `minusWord#` y#))
+ (W32# x#) * (W32# y#) = W32# (wordToWord32# (x# `timesWord#` y#))
+ negate (W32# x#) = W32# (wordToWord32# (int2Word# (negateInt# (word2Int# x#))))
+ abs x = x
+ signum 0 = 0
+ signum _ = 1
+ fromInteger (S# i#) = W32# (wordToWord32# (int2Word# i#))
+ fromInteger (J# s# d#) = W32# (wordToWord32# (integer2Word# s# d#))
+
+instance Real Word32 where
+ toRational x = toInteger x % 1
+
+instance Enum Word32 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Word32"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Word32"
+ toEnum i@(I# i#)
+ | i >= 0
+#if WORD_SIZE_IN_BYTES == 8
+ && i <= fromIntegral (maxBound::Word32)
+#endif
+ = W32# (int2Word# i#)
+ | otherwise = toEnumError "Word32" i (minBound::Word32, maxBound::Word32)
+#if WORD_SIZE_IN_BYTES == 4
+ fromEnum x@(W32# x#)
+ | x <= fromIntegral (maxBound::Int)
+ = I# (word2Int# x#)
+ | otherwise = fromEnumError "Word32" x
+ enumFrom = integralEnumFrom
+ enumFromThen = integralEnumFromThen
+ enumFromTo = integralEnumFromTo
+ enumFromThenTo = integralEnumFromThenTo
+#else
+ fromEnum (W32# x#) = I# (word2Int# x#)
+ enumFrom = boundedEnumFrom
+ enumFromThen = boundedEnumFromThen
+#endif
+
+instance Integral Word32 where
+ quot x@(W32# x#) y@(W32# y#)
+ | y /= 0 = W32# (x# `quotWord#` y#)
+ | otherwise = divZeroError "quot{Word32}" x
+ rem x@(W32# x#) y@(W32# y#)
+ | y /= 0 = W32# (x# `remWord#` y#)
+ | otherwise = divZeroError "rem{Word32}" x
+ div x@(W32# x#) y@(W32# y#)
+ | y /= 0 = W32# (x# `quotWord#` y#)
+ | otherwise = divZeroError "div{Word32}" x
+ mod x@(W32# x#) y@(W32# y#)
+ | y /= 0 = W32# (x# `remWord#` y#)
+ | otherwise = divZeroError "mod{Word32}" x
+ quotRem x@(W32# x#) y@(W32# y#)
+ | y /= 0 = (W32# (x# `quotWord#` y#), W32# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word32}" x
+ divMod x@(W32# x#) y@(W32# y#)
+ | y /= 0 = (W32# (x# `quotWord#` y#), W32# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word32}" x
+ toInteger (W32# x#)
+#if WORD_SIZE_IN_BYTES == 4
+ | i# >=# 0# = S# i#
+ | otherwise = case word2Integer# x# of (# s, d #) -> J# s d
+ where
+ i# = word2Int# x#
+#else
+ = S# (word2Int# x#)
+#endif
+
+instance Bounded Word32 where
+ minBound = 0
+ maxBound = 0xFFFFFFFF
+
+instance Ix Word32 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Word32"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Word32 where
+#if WORD_SIZE_IN_BYTES == 4
+ readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]
+#else
+ readsPrec p s = [(fromIntegral (x::Int), r) | (x, r) <- readsPrec p s]
+#endif
+
+instance Bits Word32 where
+ (W32# x#) .&. (W32# y#) = W32# (x# `and#` y#)
+ (W32# x#) .|. (W32# y#) = W32# (x# `or#` y#)
+ (W32# x#) `xor` (W32# y#) = W32# (x# `xor#` y#)
+ complement (W32# x#) = W32# (x# `xor#` mb#) where W32# mb# = maxBound
+ (W32# x#) `shift` (I# i#)
+ | i# >=# 0# = W32# (wordToWord32# (x# `shiftL#` i#))
+ | otherwise = W32# (x# `shiftRL#` negateInt# i#)
+ (W32# x#) `rotate` (I# i#) = W32# (wordToWord32# ((x# `shiftL#` i'#) `or#`
+ (x# `shiftRL#` (32# -# i'#))))
+ where
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 31#)
+ bitSize _ = 32
+ isSigned _ = False
+
+{-# RULES
+"fromIntegral/Word8->Word32" fromIntegral = \(W8# x#) -> W32# x#
+"fromIntegral/Word16->Word32" fromIntegral = \(W16# x#) -> W32# x#
+"fromIntegral/Word32->Word32" fromIntegral = id :: Word32 -> Word32
+"fromIntegral/Word32->Integer" fromIntegral = toInteger :: Word32 -> Integer
+"fromIntegral/a->Word32" fromIntegral = \x -> case fromIntegral x of W# x# -> W32# (wordToWord32# x#)
+"fromIntegral/Word32->a" fromIntegral = \(W32# x#) -> fromIntegral (W# x#)
+ #-}
+
+------------------------------------------------------------------------
+-- type Word64
+------------------------------------------------------------------------
+
+#if WORD_SIZE_IN_BYTES == 4
+
+data Word64 = W64# Word64#
+
+instance Eq Word64 where
+ (W64# x#) == (W64# y#) = x# `eqWord64#` y#
+ (W64# x#) /= (W64# y#) = x# `neWord64#` y#
+
+instance Ord Word64 where
+ (W64# x#) < (W64# y#) = x# `ltWord64#` y#
+ (W64# x#) <= (W64# y#) = x# `leWord64#` y#
+ (W64# x#) > (W64# y#) = x# `gtWord64#` y#
+ (W64# x#) >= (W64# y#) = x# `geWord64#` y#
+
+instance Num Word64 where
+ (W64# x#) + (W64# y#) = W64# (int64ToWord64# (word64ToInt64# x# `plusInt64#` word64ToInt64# y#))
+ (W64# x#) - (W64# y#) = W64# (int64ToWord64# (word64ToInt64# x# `minusInt64#` word64ToInt64# y#))
+ (W64# x#) * (W64# y#) = W64# (int64ToWord64# (word64ToInt64# x# `timesInt64#` word64ToInt64# y#))
+ negate (W64# x#) = W64# (int64ToWord64# (negateInt64# (word64ToInt64# x#)))
+ abs x = x
+ signum 0 = 0
+ signum _ = 1
+ fromInteger (S# i#) = W64# (int64ToWord64# (intToInt64# i#))
+ fromInteger (J# s# d#) = W64# (integerToWord64# s# d#)
+
+instance Enum Word64 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Word64"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Word64"
+ toEnum i@(I# i#)
+ | i >= 0 = W64# (wordToWord64# (int2Word# i#))
+ | otherwise = toEnumError "Word64" i (minBound::Word64, maxBound::Word64)
+ fromEnum x@(W64# x#)
+ | x <= fromIntegral (maxBound::Int)
+ = I# (word2Int# (word64ToWord# x#))
+ | otherwise = fromEnumError "Word64" x
+ enumFrom = integralEnumFrom
+ enumFromThen = integralEnumFromThen
+ enumFromTo = integralEnumFromTo
+ enumFromThenTo = integralEnumFromThenTo
+
+instance Integral Word64 where
+ quot x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `quotWord64#` y#)
+ | otherwise = divZeroError "quot{Word64}" x
+ rem x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `remWord64#` y#)
+ | otherwise = divZeroError "rem{Word64}" x
+ div x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `quotWord64#` y#)
+ | otherwise = divZeroError "div{Word64}" x
+ mod x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `remWord64#` y#)
+ | otherwise = divZeroError "mod{Word64}" x
+ quotRem x@(W64# x#) y@(W64# y#)
+ | y /= 0 = (W64# (x# `quotWord64#` y#), W64# (x# `remWord64#` y#))
+ | otherwise = divZeroError "quotRem{Word64}" x
+ divMod x@(W64# x#) y@(W64# y#)
+ | y /= 0 = (W64# (x# `quotWord64#` y#), W64# (x# `remWord64#` y#))
+ | otherwise = divZeroError "quotRem{Word64}" x
+ toInteger x@(W64# x#)
+ | x <= 0x7FFFFFFF = S# (word2Int# (word64ToWord# x#))
+ | otherwise = case word64ToInteger# x# of (# s, d #) -> J# s d
+
+instance Bits Word64 where
+ (W64# x#) .&. (W64# y#) = W64# (x# `and64#` y#)
+ (W64# x#) .|. (W64# y#) = W64# (x# `or64#` y#)
+ (W64# x#) `xor` (W64# y#) = W64# (x# `xor64#` y#)
+ complement (W64# x#) = W64# (not64# x#)
+ (W64# x#) `shift` (I# i#)
+ | i# >=# 0# = W64# (x# `shiftL64#` i#)
+ | otherwise = W64# (x# `shiftRL64#` negateInt# i#)
+ (W64# x#) `rotate` (I# i#) = W64# ((x# `shiftL64#` i'#) `or64#`
+ (x# `shiftRL64#` (64# -# i'#)))
+ where
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)
+ bitSize _ = 64
+ isSigned _ = False
+
+foreign import "stg_eqWord64" unsafe eqWord64# :: Word64# -> Word64# -> Bool
+foreign import "stg_neWord64" unsafe neWord64# :: Word64# -> Word64# -> Bool
+foreign import "stg_ltWord64" unsafe ltWord64# :: Word64# -> Word64# -> Bool
+foreign import "stg_leWord64" unsafe leWord64# :: Word64# -> Word64# -> Bool
+foreign import "stg_gtWord64" unsafe gtWord64# :: Word64# -> Word64# -> Bool
+foreign import "stg_geWord64" unsafe geWord64# :: Word64# -> Word64# -> Bool
+foreign import "stg_int64ToWord64" unsafe int64ToWord64# :: Int64# -> Word64#
+foreign import "stg_word64ToInt64" unsafe word64ToInt64# :: Word64# -> Int64#
+foreign import "stg_plusInt64" unsafe plusInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_minusInt64" unsafe minusInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_timesInt64" unsafe timesInt64# :: Int64# -> Int64# -> Int64#
+foreign import "stg_negateInt64" unsafe negateInt64# :: Int64# -> Int64#
+foreign import "stg_intToInt64" unsafe intToInt64# :: Int# -> Int64#
+foreign import "stg_wordToWord64" unsafe wordToWord64# :: Word# -> Word64#
+foreign import "stg_word64ToWord" unsafe word64ToWord# :: Word64# -> Word#
+foreign import "stg_quotWord64" unsafe quotWord64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_remWord64" unsafe remWord64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_and64" unsafe and64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_or64" unsafe or64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_xor64" unsafe xor64# :: Word64# -> Word64# -> Word64#
+foreign import "stg_not64" unsafe not64# :: Word64# -> Word64#
+foreign import "stg_shiftL64" unsafe shiftL64# :: Word64# -> Int# -> Word64#
+foreign import "stg_shiftRL64" unsafe shiftRL64# :: Word64# -> Int# -> Word64#
+
+{-# RULES
+"fromIntegral/Int->Word64" fromIntegral = \(I# x#) -> W64# (int64ToWord64# (intToInt64# x#))
+"fromIntegral/Word->Word64" fromIntegral = \(W# x#) -> W64# (wordToWord64# x#)
+"fromIntegral/Word64->Int" fromIntegral = \(W64# x#) -> I# (word2Int# (word64ToWord# x#))
+"fromIntegral/Word64->Word" fromIntegral = \(W64# x#) -> W# (word64ToWord# x#)
+"fromIntegral/Word64->Word64" fromIntegral = id :: Word64 -> Word64
+ #-}
+
+#else
+
+data Word64 = W64# Word# deriving (Eq, Ord)
+
+instance Num Word64 where
+ (W64# x#) + (W64# y#) = W64# (x# `plusWord#` y#)
+ (W64# x#) - (W64# y#) = W64# (x# `minusWord#` y#)
+ (W64# x#) * (W64# y#) = W64# (x# `timesWord#` y#)
+ negate (W64# x#) = W64# (int2Word# (negateInt# (word2Int# x#)))
+ abs x = x
+ signum 0 = 0
+ signum _ = 1
+ fromInteger (S# i#) = W64# (int2Word# i#)
+ fromInteger (J# s# d#) = W64# (integer2Word# s# d#)
+
+instance Enum Word64 where
+ succ x
+ | x /= maxBound = x + 1
+ | otherwise = succError "Word64"
+ pred x
+ | x /= minBound = x - 1
+ | otherwise = predError "Word64"
+ toEnum i@(I# i#)
+ | i >= 0 = W64# (int2Word# i#)
+ | otherwise = toEnumError "Word64" i (minBound::Word64, maxBound::Word64)
+ fromEnum x@(W64# x#)
+ | x <= fromIntegral (maxBound::Int)
+ = I# (word2Int# x#)
+ | otherwise = fromEnumError "Word64" x
+ enumFrom = integralEnumFrom
+ enumFromThen = integralEnumFromThen
+ enumFromTo = integralEnumFromTo
+ enumFromThenTo = integralEnumFromThenTo
+
+instance Integral Word64 where
+ quot x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `quotWord#` y#)
+ | otherwise = divZeroError "quot{Word64}" x
+ rem x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `remWord#` y#)
+ | otherwise = divZeroError "rem{Word64}" x
+ div x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `quotWord#` y#)
+ | otherwise = divZeroError "div{Word64}" x
+ mod x@(W64# x#) y@(W64# y#)
+ | y /= 0 = W64# (x# `remWord#` y#)
+ | otherwise = divZeroError "mod{Word64}" x
+ quotRem x@(W64# x#) y@(W64# y#)
+ | y /= 0 = (W64# (x# `quotWord#` y#), W64# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word64}" x
+ divMod x@(W64# x#) y@(W64# y#)
+ | y /= 0 = (W64# (x# `quotWord#` y#), W64# (x# `remWord#` y#))
+ | otherwise = divZeroError "quotRem{Word64}" x
+ toInteger (W64# x#)
+ | i# >=# 0# = S# i#
+ | otherwise = case word2Integer# x# of (# s, d #) -> J# s d
+ where
+ i# = word2Int# x#
+
+instance Bits Word64 where
+ (W64# x#) .&. (W64# y#) = W64# (x# `and#` y#)
+ (W64# x#) .|. (W64# y#) = W64# (x# `or#` y#)
+ (W64# x#) `xor` (W64# y#) = W64# (x# `xor#` y#)
+ complement (W64# x#) = W64# (x# `xor#` mb#) where W64# mb# = maxBound
+ (W64# x#) `shift` (I# i#)
+ | i# >=# 0# = W64# (x# `shiftL#` i#)
+ | otherwise = W64# (x# `shiftRL#` negateInt# i#)
+ (W64# x#) `rotate` (I# i#) = W64# ((x# `shiftL#` i'#) `or#`
+ (x# `shiftRL#` (64# -# i'#)))
+ where
+ i'# = word2Int# (int2Word# i# `and#` int2Word# 63#)
+ bitSize _ = 64
+ isSigned _ = False
+
+{-# RULES
+"fromIntegral/a->Word64" fromIntegral = \x -> case fromIntegral x of W# x# -> W64# x#
+"fromIntegral/Word64->a" fromIntegral = \(W64# x#) -> fromIntegral (W# x#)
+ #-}
+
+#endif
+
+instance CCallable Word64
+instance CReturnable Word64
+
+instance Show Word64 where
+ showsPrec p x = showsPrec p (toInteger x)
+
+instance Real Word64 where
+ toRational x = toInteger x % 1
+
+instance Bounded Word64 where
+ minBound = 0
+ maxBound = 0xFFFFFFFFFFFFFFFF
+
+instance Ix Word64 where
+ range (m,n) = [m..n]
+ index b@(m,_) i
+ | inRange b i = fromIntegral (i - m)
+ | otherwise = indexError b i "Word64"
+ inRange (m,n) i = m <= i && i <= n
+
+instance Read Word64 where
+ readsPrec p s = [(fromInteger x, r) | (x, r) <- readsPrec p s]
+\end{code}
diff --git a/libraries/base/Main.hi-boot b/libraries/base/Main.hi-boot
new file mode 100644
index 0000000000..95942f1148
--- /dev/null
+++ b/libraries/base/Main.hi-boot
@@ -0,0 +1,13 @@
+---------------------------------------------------------------------------
+-- Main.hi
+--
+-- This hand-written interface file fakes a "Main" module
+-- It is used *solely* so that GHCmain generates the right kind of
+-- external reference to Main.main
+---------------------------------------------------------------------------
+
+__interface Main 1 where
+__export Main main ;
+1 main :: __forall a => GHCziIOBase.IO a; -- wish this could be __o. KSW 1999-04.
+
+
diff --git a/libraries/base/Makefile b/libraries/base/Makefile
new file mode 100644
index 0000000000..2d87d9b20a
--- /dev/null
+++ b/libraries/base/Makefile
@@ -0,0 +1,74 @@
+# -----------------------------------------------------------------------------
+# $Id: Makefile,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+
+TOP=../..
+include $(TOP)/mk/boilerplate.mk
+
+ifeq "$(way)" ""
+SUBDIRS = cbits
+else
+SUBDIRS=
+endif
+
+ALL_DIRS = \
+ Control \
+ Control/Concurrent \
+ Control/Monad \
+ Control/Monad/ST \
+ Data \
+ Data/Array \
+ Database \
+ Debug \
+ FileFormat \
+ Foreign \
+ Foreign/C \
+ Foreign/Marshal \
+ GHC \
+ Hugs \
+ Language \
+ Network \
+ NHC \
+ System \
+ System/IO \
+ Text \
+ Text/Show
+
+PRE_SRCS += $(wildcard $(patsubst %, %/*.hsc, $(ALL_DIRS)))
+SRC_HSC2HS_OPTS += -Iinclude -I.
+
+ALL_HS_SRCS = $(wildcard $(patsubst %, %/*.hs, . $(ALL_DIRS)))
+ALL_LHS_SRCS += $(wildcard GHC/*.lhs)
+ALL_HS_OBJS = $(patsubst %.hs, %.o, $(ALL_HS_SRCS)) \
+ $(patsubst %.lhs, %.o, $(ALL_LHS_SRCS))
+
+
+srcs : $(HS_SRCS) GHC/Prim.$(way_)hi
+
+# dependencies between .hsc files
+GHC/IO.hs : GHC/Handle.hs
+
+GHC/Prim.$(way_)hi : GHC/Prim.hi-boot
+ cp $< $@
+
+SRC_HC_OPTS += -cpp -fglasgow-exts -fvia-C -I$(FPTOOLS_TOP)/ghc/includes -Iinclude -package-name std -H128m $(GhcLibHcOpts)
+
+LIBNAME = libHScore$(_way).a
+
+CLEAN_FILES += $(ALL_HS_OBJS)
+
+all :: $(LIBNAME)
+
+lib : srcs
+ $(GHC_INPLACE) $(HC_OPTS) --make $(ALL_HS_SRCS) $(ALL_LHS_SRCS)
+
+$(LIBNAME) : lib
+ $(RM) $@
+ $(AR) $(AR_OPTS) $@ $(ALL_HS_OBJS)
+ $(RANLIB) $@
+
+%.o : %.hs
+ $(GHC_INPLACE) $(HC_OPTS) --make $<
+%.o : %.lhs
+ $(GHC_INPLACE) $(HC_OPTS) --make $<
+
+include $(TOP)/mk/target.mk
diff --git a/libraries/base/Prelude.hs b/libraries/base/Prelude.hs
new file mode 100644
index 0000000000..8ee9330447
--- /dev/null
+++ b/libraries/base/Prelude.hs
@@ -0,0 +1,126 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Prelude
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Prelude.hs,v 1.1 2001/06/28 14:15:01 simonmar Exp $
+--
+-- Standard module imported by default into Haskell modules.
+--
+-----------------------------------------------------------------------------
+
+module Prelude (
+
+ -- List things
+ [] (..),
+
+ map, (++), filter, concat,
+ head, last, tail, init, null, length, (!!),
+ foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1,
+ iterate, repeat, replicate, cycle,
+ take, drop, splitAt, takeWhile, dropWhile, span, break,
+ reverse, and, or,
+ any, all, elem, notElem, lookup,
+ maximum, minimum, concatMap,
+ zip, zip3, zipWith, zipWith3, unzip, unzip3,
+
+ lines, words, unlines, unwords,
+ sum, product,
+
+ -- Everything from Text.Read and Text.Show
+ ReadS, ShowS,
+ Read(readsPrec, readList),
+ Show(showsPrec, showList, show),
+ reads, shows, read, lex,
+ showChar, showString, readParen, showParen,
+
+ -- Everything corresponding to the Report's PreludeIO
+ ioError, userError, catch,
+ FilePath, IOError,
+ putChar,
+ putStr, putStrLn, print,
+ getChar,
+ getLine, getContents, interact,
+ readFile, writeFile, appendFile, readIO, readLn,
+
+ Bool(..),
+ Maybe(..),
+ Either(..),
+ Ordering(..),
+ Char, String, Int, Integer, Float, Double, IO,
+ Rational,
+ []((:), []),
+
+ module GHC.Tup,
+ -- Includes tuple types + fst, snd, curry, uncurry
+ ()(..), -- The unit type
+ (->), -- functions
+
+ Eq(..),
+ Ord(..),
+ Enum(..),
+ Bounded(..),
+ Num(..),
+ Real(..),
+ Integral(..),
+ Fractional(..),
+ Floating(..),
+ RealFrac(..),
+ RealFloat(..),
+
+ -- Monad stuff, from GHC.Base, and defined here
+ Monad(..),
+ Functor(..),
+ mapM, mapM_, sequence, sequence_, (=<<),
+
+ maybe, either,
+ (&&), (||), not, otherwise,
+ subtract, even, odd, gcd, lcm, (^), (^^),
+ fromIntegral, realToFrac,
+ --exported by GHC.Tup: fst, snd, curry, uncurry,
+ id, const, (.), flip, ($), until,
+ asTypeOf, error, undefined,
+ seq, ($!)
+
+ ) where
+
+import Control.Monad
+import System.IO
+import Text.Read
+import Text.Show
+import Data.List
+import Data.Either
+import Data.Maybe
+import Data.Bool
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.IOBase
+import GHC.Exception
+import GHC.Read
+import GHC.Enum
+import GHC.Num
+import GHC.Real
+import GHC.Float
+import GHC.Tup
+import GHC.Show
+import GHC.Conc
+import GHC.Err ( error, undefined )
+#endif
+
+infixr 0 $!
+
+
+-- -----------------------------------------------------------------------------
+-- Miscellaneous functions
+
+($!) :: (a -> b) -> a -> b
+f $! x = x `seq` f x
+
+
diff --git a/libraries/base/System/CPUTime.hsc b/libraries/base/System/CPUTime.hsc
new file mode 100644
index 0000000000..b800e8c0b9
--- /dev/null
+++ b/libraries/base/System/CPUTime.hsc
@@ -0,0 +1,126 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.CPUTime
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: CPUTime.hsc,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- The standard CPUTime library.
+--
+-----------------------------------------------------------------------------
+
+module System.CPUTime
+ (
+ getCPUTime, -- :: IO Integer
+ cpuTimePrecision -- :: Integer
+ ) where
+
+import Prelude
+
+import Foreign
+import Foreign.C
+
+import Data.Ratio
+
+#include "HsCore.h"
+
+-- -----------------------------------------------------------------------------
+-- Computation `getCPUTime' returns the number of picoseconds CPU time
+-- used by the current program. The precision of this result is
+-- implementation-dependent.
+
+-- The `cpuTimePrecision' constant is the smallest measurable difference
+-- in CPU time that the implementation can record, and is given as an
+-- integral number of picoseconds.
+
+getCPUTime :: IO Integer
+getCPUTime = do
+
+#ifndef _WIN32
+-- getrusage() is right royal pain to deal with when targetting multiple
+-- versions of Solaris, since some versions supply it in libc (2.3 and 2.5),
+-- while 2.4 has got it in libucb (I wouldn't be too surprised if it was back
+-- again in libucb in 2.6..)
+--
+-- Avoid the problem by resorting to times() instead.
+--
+#if defined(HAVE_GETRUSAGE) && ! irix_TARGET_OS && ! solaris2_TARGET_OS
+ allocaBytes (#const sizeof(struct rusage)) $ \ p_rusage -> do
+ getrusage (#const RUSAGE_SELF) p_rusage
+
+ let ru_utime = (#ptr struct rusage, ru_utime) p_rusage
+ let ru_stime = (#ptr struct rusage, ru_stime) p_rusage
+ u_sec <- (#peek struct timeval,tv_sec) ru_utime :: IO CLong
+ u_usec <- (#peek struct timeval,tv_usec) ru_utime :: IO CLong
+ s_sec <- (#peek struct timeval,tv_sec) ru_stime :: IO CLong
+ s_usec <- (#peek struct timeval,tv_usec) ru_stime :: IO CLong
+
+ return ((fromIntegral u_sec * 1000000 + fromIntegral u_usec +
+ fromIntegral s_sec * 1000000 + fromIntegral s_usec)
+ * 1000000)
+
+type CRUsage = ()
+foreign import unsafe getrusage :: CInt -> Ptr CRUsage -> IO CInt
+#else
+# if defined(HAVE_TIMES)
+ allocaBytes (#const sizeof(struct tms)) $ \ p_tms -> do
+ times p_tms
+ u_ticks <- (#peek struct tms,tms_utime) p_tms :: IO CClock
+ s_ticks <- (#peek struct tms,tms_stime) p_tms :: IO CClock
+ return (( (fromIntegral u_ticks + fromIntegral s_ticks) * 1000000000000)
+ `div` clockTicks)
+
+type CTms = ()
+foreign import unsafe times :: Ptr CTms -> CClock
+# else
+ ioException (IOError Nothing UnsupportedOperation
+ "getCPUTime"
+ "can't get CPU time"
+ Nothing)
+# endif
+#endif
+
+#else /* _WIN32 */
+ allocaBytes (#const sizeof(FILETIME)) $ \ p_creationTime -> do
+ allocaBytes (#const sizeof(FILETIME)) $ \ p_exitTime -> do
+ allocaBytes (#const sizeof(FILETIME)) $ \ p_kernelTime -> do
+ allocaBytes (#const sizeof(FILETIME)) $ \ p_userTime -> do
+ pid <- getCurrentProcess
+ ok <- getProcessTimes pid p_creationTime p_exitTime p_kernelTime p_userTime
+ if toBool ok then do
+ ut <- ft2usecs p_userTime
+ kt <- ft2usecs p_kernelTime
+ return (fromIntegral (ut + kt))
+ else return 0
+ where ft2usecs ft = do
+ high <- (#peek FILETIME,dwHighDateTime) ft :: IO CLong
+ low <- (#peek FILETIME,dwLowDateTime) ft :: IO CLong
+ return (high * (2^32) + low)
+
+ -- ToDo: pin down elapsed times to just the OS thread(s) that
+ -- are evaluating/managing Haskell code.
+
+type FILETIME = ()
+type HANDLE = ()
+-- need proper Haskell names (initial lower-case character)
+foreign import "GetCurrentProcess" unsafe getCurrentProcess :: IO (Ptr HANDLE)
+foreign import "GetProcessTimes" unsafe getProcessTimes :: Ptr HANDLE -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> IO CInt
+
+#endif /* not _WIN32 */
+
+cpuTimePrecision :: Integer
+cpuTimePrecision = round ((1000000000000::Integer) % fromIntegral (clockTicks))
+
+clockTicks :: Int
+clockTicks =
+#if defined(CLK_TCK)
+ (#const CLK_TCK)
+#else
+ unsafePerformIO (sysconf (#const _SC_CLK_TCK) >>= return . fromIntegral)
+foreign import unsafe sysconf :: CInt -> IO CLong
+#endif
diff --git a/libraries/base/System/Cmd.hsc b/libraries/base/System/Cmd.hsc
new file mode 100644
index 0000000000..2deb48cd00
--- /dev/null
+++ b/libraries/base/System/Cmd.hsc
@@ -0,0 +1,55 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Cmd
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Cmd.hsc,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Executing a command.
+--
+-----------------------------------------------------------------------------
+
+module System.Cmd
+ ( system -- :: String -> IO ExitCode
+ ) where
+
+import Prelude
+
+import System.Exit
+import Foreign.C
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.IOBase
+#endif
+
+#include "HsCore.h"
+
+-- ---------------------------------------------------------------------------
+-- system
+
+-- Computation `system cmd' returns the exit code
+-- produced when the operating system processes the command `cmd'.
+
+-- This computation may fail with
+-- PermissionDenied
+-- The process has insufficient privileges to perform the operation.
+-- ResourceExhausted
+-- Insufficient resources are available to perform the operation.
+-- UnsupportedOperation
+-- The implementation does not support system calls.
+
+system :: String -> IO ExitCode
+system "" = ioException (IOError Nothing InvalidArgument "system" "null command" Nothing)
+system cmd =
+ withUnsafeCString cmd $ \s -> do
+ status <- throwErrnoIfMinus1 "system" (primSystem s)
+ case status of
+ 0 -> return ExitSuccess
+ n -> return (ExitFailure n)
+
+foreign import ccall "systemCmd" unsafe primSystem :: UnsafeCString -> IO Int
diff --git a/libraries/base/System/Environment.hs b/libraries/base/System/Environment.hs
new file mode 100644
index 0000000000..d2b0d38e54
--- /dev/null
+++ b/libraries/base/System/Environment.hs
@@ -0,0 +1,83 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Environment
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Environment.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Miscellaneous information about the system environment.
+--
+-----------------------------------------------------------------------------
+
+module System.Environment
+ (
+ , getArgs -- :: IO [String]
+ , getProgName -- :: IO String
+ , getEnv -- :: String -> IO String
+ ) where
+
+import Prelude
+
+import Foreign
+import Foreign.C
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.IOBase
+#endif
+
+-- ---------------------------------------------------------------------------
+-- getArgs, getProgName, getEnv
+
+-- Computation `getArgs' returns a list of the program's command
+-- line arguments (not including the program name).
+
+getArgs :: IO [String]
+getArgs = do
+ argv <- peek prog_argv_label
+ argc <- peek prog_argc_label
+ peekArray (fromIntegral argc - 1) (advancePtr argv 1) >>= mapM peekCString
+
+foreign label "prog_argv" prog_argv_label :: Ptr (Ptr (Ptr CChar))
+foreign label "prog_argc" prog_argc_label :: Ptr CInt
+
+-- Computation `getProgName' returns the name of the program
+-- as it was invoked.
+
+getProgName :: IO String
+getProgName = do
+ argv <- peek prog_argv_label
+ unpackProgName argv
+
+unpackProgName :: Ptr (Ptr CChar) -> IO String -- argv[0]
+unpackProgName argv = do
+ s <- peekElemOff argv 0 >>= peekCString
+ return (de_slash "" s)
+ where
+ -- re-start accumulating at every '/'
+ de_slash :: String -> String -> String
+ de_slash acc [] = reverse acc
+ de_slash _acc ('/':xs) = de_slash [] xs
+ de_slash acc (x:xs) = de_slash (x:acc) xs
+
+-- Computation `getEnv var' returns the value
+-- of the environment variable {\em var}.
+
+-- This computation may fail with
+-- NoSuchThing: The environment variable does not exist.
+
+getEnv :: String -> IO String
+getEnv name =
+ withUnsafeCString name $ \s -> do
+ litstring <- c_getenv s
+ if litstring /= nullPtr
+ then peekCString litstring
+ else ioException (IOError Nothing NoSuchThing "getEnv"
+ "no environment variable" (Just name))
+
+foreign import ccall "getenv" unsafe
+ c_getenv :: UnsafeCString -> IO (Ptr CChar)
diff --git a/libraries/base/System/Exit.hs b/libraries/base/System/Exit.hs
new file mode 100644
index 0000000000..28597adced
--- /dev/null
+++ b/libraries/base/System/Exit.hs
@@ -0,0 +1,44 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Exit
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Exit.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Exiting the program.
+--
+-----------------------------------------------------------------------------
+
+module System.Exit
+ (
+ ExitCode(ExitSuccess,ExitFailure)
+ , exitWith -- :: ExitCode -> IO a
+ , exitFailure -- :: IO a
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.IOBase
+#endif
+
+-- ---------------------------------------------------------------------------
+-- exitWith
+
+-- `exitWith code' terminates the program, returning `code' to the
+-- program's caller. Before it terminates, any open or semi-closed
+-- handles are first closed.
+
+exitWith :: ExitCode -> IO a
+exitWith ExitSuccess = throw (ExitException ExitSuccess)
+exitWith code@(ExitFailure n)
+ | n == 0 = ioException (IOError Nothing InvalidArgument "exitWith" "ExitFailure 0" Nothing)
+ | otherwise = throw (ExitException code)
+
+exitFailure :: IO a
+exitFailure = exitWith (ExitFailure 1)
diff --git a/libraries/base/System/IO.hs b/libraries/base/System/IO.hs
new file mode 100644
index 0000000000..752ae9babb
--- /dev/null
+++ b/libraries/base/System/IO.hs
@@ -0,0 +1,192 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : System.IO
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: IO.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- The standard IO library.
+--
+-----------------------------------------------------------------------------
+
+module System.IO (
+ Handle, -- abstract, instance of: Eq, Show.
+ HandlePosn(..), -- abstract, instance of: Eq, Show.
+
+ IOMode(ReadMode,WriteMode,AppendMode,ReadWriteMode),
+ BufferMode(NoBuffering,LineBuffering,BlockBuffering),
+ SeekMode(AbsoluteSeek,RelativeSeek,SeekFromEnd),
+
+ stdin, stdout, stderr, -- :: Handle
+
+ openFile, -- :: FilePath -> IOMode -> IO Handle
+ hClose, -- :: Handle -> IO ()
+ hFileSize, -- :: Handle -> IO Integer
+ hIsEOF, -- :: Handle -> IO Bool
+ isEOF, -- :: IO Bool
+
+ hSetBuffering, -- :: Handle -> BufferMode -> IO ()
+ hGetBuffering, -- :: Handle -> IO BufferMode
+ hFlush, -- :: Handle -> IO ()
+ hGetPosn, -- :: Handle -> IO HandlePosn
+ hSetPosn, -- :: HandlePosn -> IO ()
+ hSeek, -- :: Handle -> SeekMode -> Integer -> IO ()
+ hWaitForInput, -- :: Handle -> Int -> IO Bool
+ hReady, -- :: Handle -> IO Bool
+ hGetChar, -- :: Handle -> IO Char
+ hGetLine, -- :: Handle -> IO [Char]
+ hLookAhead, -- :: Handle -> IO Char
+ hGetContents, -- :: Handle -> IO [Char]
+ hPutChar, -- :: Handle -> Char -> IO ()
+ hPutStr, -- :: Handle -> [Char] -> IO ()
+ hPutStrLn, -- :: Handle -> [Char] -> IO ()
+ hPrint, -- :: Show a => Handle -> a -> IO ()
+ hIsOpen, hIsClosed, -- :: Handle -> IO Bool
+ hIsReadable, hIsWritable, -- :: Handle -> IO Bool
+ hIsSeekable, -- :: Handle -> IO Bool
+
+ isAlreadyExistsError, isDoesNotExistError, -- :: IOError -> Bool
+ isAlreadyInUseError, isFullError,
+ isEOFError, isIllegalOperation,
+ isPermissionError, isUserError,
+
+ ioeGetErrorString, -- :: IOError -> String
+ ioeGetHandle, -- :: IOError -> Maybe Handle
+ ioeGetFileName, -- :: IOError -> Maybe FilePath
+
+ try, -- :: IO a -> IO (Either IOError a)
+ bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
+ bracket_, -- :: IO a -> (a -> IO b) -> IO c -> IO c
+
+ -- Non-standard extension (but will hopefully become standard with 1.5) is
+ -- to export the Prelude io functions via IO (in addition to exporting them
+ -- from the prelude...for now.)
+ IO,
+ FilePath, -- :: String
+ IOError,
+ ioError, -- :: IOError -> IO a
+ userError, -- :: String -> IOError
+ catch, -- :: IO a -> (IOError -> IO a) -> IO a
+ interact, -- :: (String -> String) -> IO ()
+
+ putChar, -- :: Char -> IO ()
+ putStr, -- :: String -> IO ()
+ putStrLn, -- :: String -> IO ()
+ print, -- :: Show a => a -> IO ()
+ getChar, -- :: IO Char
+ getLine, -- :: IO String
+ getContents, -- :: IO String
+ readFile, -- :: FilePath -> IO String
+ writeFile, -- :: FilePath -> String -> IO ()
+ appendFile, -- :: FilePath -> String -> IO ()
+ readIO, -- :: Read a => String -> IO a
+ readLn, -- :: Read a => IO a
+
+ hPutBuf, -- :: Handle -> Ptr a -> Int -> IO ()
+ hGetBuf, -- :: Handle -> Ptr a -> Int -> IO Int
+
+ fixIO, -- :: (a -> IO a) -> IO a
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.IOBase -- Together these four Prelude modules define
+import GHC.Handle -- all the stuff exported by IO for the GHC version
+import GHC.IO
+import GHC.ST ( fixST )
+import GHC.Exception
+import GHC.Num
+import GHC.Read
+import GHC.Show
+#endif
+
+import Data.Dynamic
+
+-- -----------------------------------------------------------------------------
+-- Typeable instance for Handle
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(Handle,handleTc,"Handle")
+
+-- -----------------------------------------------------------------------------
+-- Standard IO
+
+putChar :: Char -> IO ()
+putChar c = hPutChar stdout c
+
+putStr :: String -> IO ()
+putStr s = hPutStr stdout s
+
+putStrLn :: String -> IO ()
+putStrLn s = do putStr s
+ putChar '\n'
+
+print :: Show a => a -> IO ()
+print x = putStrLn (show x)
+
+getChar :: IO Char
+getChar = hGetChar stdin
+
+getLine :: IO String
+getLine = hGetLine stdin
+
+getContents :: IO String
+getContents = hGetContents stdin
+
+interact :: (String -> String) -> IO ()
+interact f = do s <- getContents
+ putStr (f s)
+
+readFile :: FilePath -> IO String
+readFile name = openFile name ReadMode >>= hGetContents
+
+writeFile :: FilePath -> String -> IO ()
+writeFile name str = do
+ hdl <- openFile name WriteMode
+ hPutStr hdl str
+ hClose hdl
+
+appendFile :: FilePath -> String -> IO ()
+appendFile name str = do
+ hdl <- openFile name AppendMode
+ hPutStr hdl str
+ hClose hdl
+
+readLn :: Read a => IO a
+readLn = do l <- getLine
+ r <- readIO l
+ return r
+
+-- raises an exception instead of an error
+readIO :: Read a => String -> IO a
+readIO s = case (do { (x,t) <- reads s ;
+ ("","") <- lex t ;
+ return x }) of
+ [x] -> return x
+ [] -> ioError (userError "Prelude.readIO: no parse")
+ _ -> ioError (userError "Prelude.readIO: ambiguous parse")
+
+hReady :: Handle -> IO Bool
+hReady h = hWaitForInput h 0
+
+hPutStrLn :: Handle -> String -> IO ()
+hPutStrLn hndl str = do
+ hPutStr hndl str
+ hPutChar hndl '\n'
+
+hPrint :: Show a => Handle -> a -> IO ()
+hPrint hdl = hPutStrLn hdl . show
+
+-- ---------------------------------------------------------------------------
+-- fixIO
+
+#ifdef __GLASGOW_HASKELL__
+fixIO :: (a -> IO a) -> IO a
+fixIO m = stToIO (fixST (ioToST . m))
+#endif
diff --git a/libraries/base/System/IO/Directory.hsc b/libraries/base/System/IO/Directory.hsc
new file mode 100644
index 0000000000..8a23831740
--- /dev/null
+++ b/libraries/base/System/IO/Directory.hsc
@@ -0,0 +1,555 @@
+-- -----------------------------------------------------------------------------
+-- $Id: Directory.hsc,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- (c) The University of Glasgow, 1994-2000
+--
+
+-- The Directory Interface
+
+{-
+A directory contains a series of entries, each of which is a named
+reference to a file system object (file, directory etc.). Some
+entries may be hidden, inaccessible, or have some administrative
+function (e.g. "." or ".." under POSIX), but in this standard all such
+entries are considered to form part of the directory contents.
+Entries in sub-directories are not, however, considered to form part
+of the directory contents.
+
+Each file system object is referenced by a {\em path}. There is
+normally at least one absolute path to each file system object. In
+some operating systems, it may also be possible to have paths which
+are relative to the current directory.
+-}
+
+module System.IO.Directory
+ (
+ Permissions -- abstract
+
+ , readable -- :: Permissions -> Bool
+ , writable -- :: Permissions -> Bool
+ , executable -- :: Permissions -> Bool
+ , searchable -- :: Permissions -> Bool
+
+ , createDirectory -- :: FilePath -> IO ()
+ , removeDirectory -- :: FilePath -> IO ()
+ , renameDirectory -- :: FilePath -> FilePath -> IO ()
+
+ , getDirectoryContents -- :: FilePath -> IO [FilePath]
+ , getCurrentDirectory -- :: IO FilePath
+ , setCurrentDirectory -- :: FilePath -> IO ()
+
+ , removeFile -- :: FilePath -> IO ()
+ , renameFile -- :: FilePath -> FilePath -> IO ()
+
+ , doesFileExist -- :: FilePath -> IO Bool
+ , doesDirectoryExist -- :: FilePath -> IO Bool
+
+ , getPermissions -- :: FilePath -> IO Permissions
+ , setPermissions -- :: FilePath -> Permissions -> IO ()
+
+ , getModificationTime -- :: FilePath -> IO ClockTime
+ ) where
+
+import Prelude
+
+import System.Time ( ClockTime(..) )
+import System.IO
+import Foreign
+import Foreign.C
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Posix
+import GHC.IOBase ( IOException(..), IOErrorType(..), ioException )
+#endif
+
+-- to get config.h
+#include "HsCore.h"
+
+#include <sys/stat.h>
+#include <dirent.h>
+#include <limits.h>
+#include <errno.h>
+#include <unistd.h>
+
+-----------------------------------------------------------------------------
+-- Permissions
+
+-- The Permissions type is used to record whether certain
+-- operations are permissible on a file/directory:
+-- [to whom? - presumably the "current user"]
+
+data Permissions
+ = Permissions {
+ readable, writable,
+ executable, searchable :: Bool
+ } deriving (Eq, Ord, Read, Show)
+
+-----------------------------------------------------------------------------
+-- Implementation
+
+-- `createDirectory dir' creates a new directory dir which is
+-- initially empty, or as near to empty as the operating system
+-- allows.
+
+-- The operation may fail with:
+
+{-
+\begin{itemize}
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EROFS, EACCES]@
+\item @isAlreadyExistsError@ / @AlreadyExists@
+The operand refers to a directory that already exists.
+@ [EEXIST]@
+\item @HardwareFault@
+A physical I/O error has occurred.
+@ [EIO]@
+\item @InvalidArgument@
+The operand is not a valid directory name.
+@[ENAMETOOLONG, ELOOP]@
+\item @NoSuchThing@
+There is no path to the directory.
+@[ENOENT, ENOTDIR]@
+\item @ResourceExhausted@
+Insufficient resources (virtual memory, process file descriptors,
+physical disk space, etc.) are available to perform the operation.
+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
+\item @InappropriateType@
+The path refers to an existing non-directory object.
+@[EEXIST]@
+\end{itemize}
+-}
+
+createDirectory :: FilePath -> IO ()
+createDirectory path = do
+ withUnsafeCString path $ \s -> do
+ throwErrnoIfMinus1Retry_ "createDirectory" $
+#if defined(mingw32_TARGET_OS)
+ mkdir s
+#else
+ mkdir s 0o777
+#endif
+
+{-
+@removeDirectory dir@ removes an existing directory {\em dir}. The
+implementation may specify additional constraints which must be
+satisfied before a directory can be removed (e.g. the directory has to
+be empty, or may not be in use by other processes). It is not legal
+for an implementation to partially remove a directory unless the
+entire directory is removed. A conformant implementation need not
+support directory removal in all situations (e.g. removal of the root
+directory).
+
+The operation may fail with:
+\begin{itemize}
+\item @HardwareFault@
+A physical I/O error has occurred.
+[@EIO@]
+\item @InvalidArgument@
+The operand is not a valid directory name.
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExist@ / @NoSuchThing@
+The directory does not exist.
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EROFS, EACCES, EPERM]@
+\item @UnsatisfiedConstraints@
+Implementation-dependent constraints are not satisfied.
+@[EBUSY, ENOTEMPTY, EEXIST]@
+\item @UnsupportedOperation@
+The implementation does not support removal in this situation.
+@[EINVAL]@
+\item @InappropriateType@
+The operand refers to an existing non-directory object.
+@[ENOTDIR]@
+\end{itemize}
+-}
+
+removeDirectory :: FilePath -> IO ()
+removeDirectory path = do
+ withUnsafeCString path $ \s ->
+ throwErrnoIfMinus1Retry_ "removeDirectory" (rmdir s)
+
+{-
+@Removefile file@ removes the directory entry for an existing file
+{\em file}, where {\em file} is not itself a directory. The
+implementation may specify additional constraints which must be
+satisfied before a file can be removed (e.g. the file may not be in
+use by other processes).
+
+The operation may fail with:
+\begin{itemize}
+\item @HardwareFault@
+A physical I/O error has occurred.
+@[EIO]@
+\item @InvalidArgument@
+The operand is not a valid file name.
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExist@ / @NoSuchThing@
+The file does not exist.
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EROFS, EACCES, EPERM]@
+\item @UnsatisfiedConstraints@
+Implementation-dependent constraints are not satisfied.
+@[EBUSY]@
+\item @InappropriateType@
+The operand refers to an existing directory.
+@[EPERM, EINVAL]@
+\end{itemize}
+-}
+
+removeFile :: FilePath -> IO ()
+removeFile path = do
+ withUnsafeCString path $ \s ->
+ throwErrnoIfMinus1Retry_ "removeFile" (unlink s)
+
+{-
+@renameDirectory@ {\em old} {\em new} changes the name of an existing
+directory from {\em old} to {\em new}. If the {\em new} directory
+already exists, it is atomically replaced by the {\em old} directory.
+If the {\em new} directory is neither the {\em old} directory nor an
+alias of the {\em old} directory, it is removed as if by
+$removeDirectory$. A conformant implementation need not support
+renaming directories in all situations (e.g. renaming to an existing
+directory, or across different physical devices), but the constraints
+must be documented.
+
+The operation may fail with:
+\begin{itemize}
+\item @HardwareFault@
+A physical I/O error has occurred.
+@[EIO]@
+\item @InvalidArgument@
+Either operand is not a valid directory name.
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
+The original directory does not exist, or there is no path to the target.
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EROFS, EACCES, EPERM]@
+\item @ResourceExhausted@
+Insufficient resources are available to perform the operation.
+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
+\item @UnsatisfiedConstraints@
+Implementation-dependent constraints are not satisfied.
+@[EBUSY, ENOTEMPTY, EEXIST]@
+\item @UnsupportedOperation@
+The implementation does not support renaming in this situation.
+@[EINVAL, EXDEV]@
+\item @InappropriateType@
+Either path refers to an existing non-directory object.
+@[ENOTDIR, EISDIR]@
+\end{itemize}
+-}
+
+renameDirectory :: FilePath -> FilePath -> IO ()
+renameDirectory opath npath =
+ withFileStatus opath $ \st -> do
+ is_dir <- isDirectory st
+ if (not is_dir)
+ then ioException (IOError Nothing InappropriateType "renameDirectory"
+ ("not a directory") (Just opath))
+ else do
+
+ withUnsafeCString opath $ \s1 ->
+ withUnsafeCString npath $ \s2 ->
+ throwErrnoIfMinus1Retry_ "renameDirectory" (rename s1 s2)
+
+{-
+@renameFile@ {\em old} {\em new} changes the name of an existing file system
+object from {\em old} to {\em new}. If the {\em new} object already
+exists, it is atomically replaced by the {\em old} object. Neither
+path may refer to an existing directory. A conformant implementation
+need not support renaming files in all situations (e.g. renaming
+across different physical devices), but the constraints must be
+documented.
+
+The operation may fail with:
+\begin{itemize}
+\item @HardwareFault@
+A physical I/O error has occurred.
+@[EIO]@
+\item @InvalidArgument@
+Either operand is not a valid file name.
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
+The original file does not exist, or there is no path to the target.
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EROFS, EACCES, EPERM]@
+\item @ResourceExhausted@
+Insufficient resources are available to perform the operation.
+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
+\item @UnsatisfiedConstraints@
+Implementation-dependent constraints are not satisfied.
+@[EBUSY]@
+\item @UnsupportedOperation@
+The implementation does not support renaming in this situation.
+@[EXDEV]@
+\item @InappropriateType@
+Either path refers to an existing directory.
+@[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@
+\end{itemize}
+-}
+
+renameFile :: FilePath -> FilePath -> IO ()
+renameFile opath npath =
+ withFileStatus opath $ \st -> do
+ is_dir <- isDirectory st
+ if is_dir
+ then ioException (IOError Nothing InappropriateType "renameFile"
+ "is a directory" (Just opath))
+ else do
+
+ withUnsafeCString opath $ \s1 ->
+ withUnsafeCString npath $ \s2 ->
+ throwErrnoIfMinus1Retry_ "renameFile" (rename s1 s2)
+
+{-
+@getDirectoryContents dir@ returns a list of {\em all} entries
+in {\em dir}.
+
+The operation may fail with:
+\begin{itemize}
+\item @HardwareFault@
+A physical I/O error has occurred.
+@[EIO]@
+\item @InvalidArgument@
+The operand is not a valid directory name.
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
+The directory does not exist.
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EACCES]@
+\item @ResourceExhausted@
+Insufficient resources are available to perform the operation.
+@[EMFILE, ENFILE]@
+\item @InappropriateType@
+The path refers to an existing non-directory object.
+@[ENOTDIR]@
+\end{itemize}
+-}
+
+getDirectoryContents :: FilePath -> IO [FilePath]
+getDirectoryContents path = do
+ p <- withUnsafeCString path $ \s ->
+ throwErrnoIfNullRetry "getDirectoryContents" (opendir s)
+ loop p
+ where
+ loop :: Ptr CDir -> IO [String]
+ loop dir = do
+ resetErrno
+ p <- readdir dir
+ if (p /= nullPtr)
+ then do
+#ifdef mingw32_TARGET_OS
+ entryp <- (#peek struct dirent,d_name) p
+ entry <- peekCString entryp -- on mingwin it's a char *, not a char []
+#else
+ entry <- peekCString ((#ptr struct dirent,d_name) p)
+#endif
+ entries <- loop dir
+ return (entry:entries)
+ else do errno <- getErrno
+ if (errno == eINTR) then loop dir else do
+ throwErrnoIfMinus1_ "getDirectoryContents" $ closedir dir
+#ifdef mingw32_TARGET_OS
+ if (errno == eNOENT) -- mingwin (20001111) cunningly sets errno to ENOENT when it runs out of files
+#else
+ if (errno == eOK)
+#endif
+ then return []
+ else throwErrno "getDirectoryContents"
+
+{-
+If the operating system has a notion of current directories,
+@getCurrentDirectory@ returns an absolute path to the
+current directory of the calling process.
+
+The operation may fail with:
+\begin{itemize}
+\item @HardwareFault@
+A physical I/O error has occurred.
+@[EIO]@
+\item @isDoesNotExistError@ / @NoSuchThing@
+There is no path referring to the current directory.
+@[EPERM, ENOENT, ESTALE...]@
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EACCES]@
+\item @ResourceExhausted@
+Insufficient resources are available to perform the operation.
+\item @UnsupportedOperation@
+The operating system has no notion of current directory.
+\end{itemize}
+-}
+
+getCurrentDirectory :: IO FilePath
+getCurrentDirectory = do
+ p <- mallocBytes (#const PATH_MAX)
+ go p (#const PATH_MAX)
+ where go p bytes = do
+ p' <- getcwd p (fromIntegral bytes)
+ if p' /= nullPtr
+ then do s <- peekCString p'
+ free p'
+ return s
+ else do errno <- getErrno
+ if errno == eRANGE
+ then do let bytes' = bytes * 2
+ p' <- reallocBytes p bytes'
+ go p' bytes'
+ else throwErrno "getCurrentDirectory"
+
+{-
+If the operating system has a notion of current directories,
+@setCurrentDirectory dir@ changes the current
+directory of the calling process to {\em dir}.
+
+The operation may fail with:
+\begin{itemize}
+\item @HardwareFault@
+A physical I/O error has occurred.
+@[EIO]@
+\item @InvalidArgument@
+The operand is not a valid directory name.
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
+The directory does not exist.
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EACCES]@
+\item @UnsupportedOperation@
+The operating system has no notion of current directory, or the
+current directory cannot be dynamically changed.
+\item @InappropriateType@
+The path refers to an existing non-directory object.
+@[ENOTDIR]@
+\end{itemize}
+-}
+
+setCurrentDirectory :: FilePath -> IO ()
+setCurrentDirectory path = do
+ withUnsafeCString path $ \s ->
+ throwErrnoIfMinus1Retry_ "setCurrentDirectory" (chdir s)
+ -- ToDo: add path to error
+
+{-
+To clarify, @doesDirectoryExist@ returns True if a file system object
+exist, and it's a directory. @doesFileExist@ returns True if the file
+system object exist, but it's not a directory (i.e., for every other
+file system object that is not a directory.)
+-}
+
+doesDirectoryExist :: FilePath -> IO Bool
+doesDirectoryExist name =
+ catch
+ (withFileStatus name $ \st -> isDirectory st)
+ (\ _ -> return False)
+
+doesFileExist :: FilePath -> IO Bool
+doesFileExist name = do
+ catch
+ (withFileStatus name $ \st -> do b <- isDirectory st; return (not b))
+ (\ _ -> return False)
+
+getModificationTime :: FilePath -> IO ClockTime
+getModificationTime name =
+ withFileStatus name $ \ st ->
+ modificationTime st
+
+getPermissions :: FilePath -> IO Permissions
+getPermissions name = do
+ withUnsafeCString name $ \s -> do
+ read <- access s (#const R_OK)
+ write <- access s (#const W_OK)
+ exec <- access s (#const X_OK)
+ withFileStatus name $ \st -> do
+ is_dir <- isDirectory st
+ is_reg <- isRegularFile st
+ return (
+ Permissions {
+ readable = read == 0,
+ writable = write == 0,
+ executable = not is_dir && exec == 0,
+ searchable = not is_reg && exec == 0
+ }
+ )
+
+setPermissions :: FilePath -> Permissions -> IO ()
+setPermissions name (Permissions r w e s) = do
+ let
+ read = if r then (#const S_IRUSR) else emptyCMode
+ write = if w then (#const S_IWUSR) else emptyCMode
+ exec = if e || s then (#const S_IXUSR) else emptyCMode
+
+ mode = read `unionCMode` (write `unionCMode` exec)
+
+ withUnsafeCString name $ \s ->
+ throwErrnoIfMinus1_ "setPermissions" $ chmod s mode
+
+withFileStatus :: FilePath -> (Ptr CStat -> IO a) -> IO a
+withFileStatus name f = do
+ allocaBytes (#const sizeof(struct stat)) $ \p ->
+ withUnsafeCString name $ \s -> do
+ throwErrnoIfMinus1Retry_ "withFileStatus" (stat s p)
+ f p
+
+modificationTime :: Ptr CStat -> IO ClockTime
+modificationTime stat = do
+ mtime <- (#peek struct stat, st_mtime) stat
+ return (TOD (toInteger (mtime :: CTime)) 0)
+
+isDirectory :: Ptr CStat -> IO Bool
+isDirectory stat = do
+ mode <- (#peek struct stat, st_mode) stat
+ return (s_ISDIR mode /= 0)
+
+isRegularFile :: Ptr CStat -> IO Bool
+isRegularFile stat = do
+ mode <- (#peek struct stat, st_mode) stat
+ return (s_ISREG mode /= 0)
+
+foreign import ccall unsafe s_ISDIR :: CMode -> Int
+#def inline HsInt s_ISDIR(m) {return S_ISDIR(m);}
+
+foreign import ccall unsafe s_ISREG :: CMode -> Int
+#def inline HsInt s_ISREG(m) {return S_ISREG(m);}
+
+emptyCMode :: CMode
+emptyCMode = 0
+
+unionCMode :: CMode -> CMode -> CMode
+unionCMode = (+)
+
+type UCString = UnsafeCString
+
+#if defined(mingw32_TARGET_OS)
+foreign import ccall unsafe mkdir :: UCString -> IO CInt
+#else
+foreign import ccall unsafe mkdir :: UCString -> CInt -> IO CInt
+#endif
+
+foreign import ccall unsafe chmod :: UCString -> CMode -> IO CInt
+foreign import ccall unsafe access :: UCString -> CMode -> IO CInt
+foreign import ccall unsafe rmdir :: UCString -> IO CInt
+foreign import ccall unsafe chdir :: UCString -> IO CInt
+foreign import ccall unsafe getcwd :: Ptr CChar -> CInt -> IO (Ptr CChar)
+foreign import ccall unsafe unlink :: UCString -> IO CInt
+foreign import ccall unsafe rename :: UCString -> UCString -> IO CInt
+
+foreign import ccall unsafe opendir :: UCString -> IO (Ptr CDir)
+foreign import ccall unsafe readdir :: Ptr CDir -> IO (Ptr CDirent)
+foreign import ccall unsafe closedir :: Ptr CDir -> IO CInt
+
+foreign import ccall unsafe stat :: UCString -> Ptr CStat -> IO CInt
+
+type CDirent = ()
diff --git a/libraries/base/System/IO/Unsafe.hs b/libraries/base/System/IO/Unsafe.hs
new file mode 100644
index 0000000000..ebe4463bfd
--- /dev/null
+++ b/libraries/base/System/IO/Unsafe.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.IO.Unsafe
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Unsafe.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- "Unsafe" IO operations.
+--
+-----------------------------------------------------------------------------
+
+module System.IO.Unsafe (
+ unsafePerformIO, -- :: IO a -> a
+ unsafeInterleaveIO, -- :: IO a -> IO a
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.IOBase
+#endif
diff --git a/libraries/base/System/Info.hs b/libraries/base/System/Info.hs
new file mode 100644
index 0000000000..b588aafb56
--- /dev/null
+++ b/libraries/base/System/Info.hs
@@ -0,0 +1,32 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Info
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Info.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Misc information about the characteristics of the host
+-- architecture/machine lucky enough to run your program.
+--
+-----------------------------------------------------------------------------
+
+#include "MachDeps.h"
+
+module System.Info
+ (
+ os, -- :: String
+ arch -- :: String
+ ) where
+
+import Prelude
+
+arch :: String
+arch = HOST_ARCH
+
+os :: String
+os = HOST_OS
diff --git a/libraries/base/System/Locale.hs b/libraries/base/System/Locale.hs
new file mode 100644
index 0000000000..cc5a34e8bf
--- /dev/null
+++ b/libraries/base/System/Locale.hs
@@ -0,0 +1,76 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Locale
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Locale.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Operations for defining locale-specific date and time formats.
+--
+-----------------------------------------------------------------------------
+
+module System.Locale
+ ( TimeLocale(..)
+ , defaultTimeLocale
+
+ , iso8601DateFormat
+ , rfc822DateFormat
+ )
+where
+
+import Prelude
+
+data TimeLocale = TimeLocale {
+ wDays :: [(String, String)], -- full and abbreviated week days
+ months :: [(String, String)], -- full and abbreviated months
+ intervals :: [(String, String)],
+ amPm :: (String, String), -- AM/PM symbols
+ dateTimeFmt, dateFmt, -- formatting strings
+ timeFmt, time12Fmt :: String
+ } deriving (Eq, Ord, Show)
+
+defaultTimeLocale :: TimeLocale
+defaultTimeLocale = TimeLocale {
+ wDays = [("Sunday", "Sun"), ("Monday", "Mon"),
+ ("Tuesday", "Tue"), ("Wednesday", "Wed"),
+ ("Thursday", "Thu"), ("Friday", "Fri"),
+ ("Saturday", "Sat")],
+
+ months = [("January", "Jan"), ("February", "Feb"),
+ ("March", "Mar"), ("April", "Apr"),
+ ("May", "May"), ("June", "Jun"),
+ ("July", "Jul"), ("August", "Aug"),
+ ("September", "Sep"), ("October", "Oct"),
+ ("November", "Nov"), ("December", "Dec")],
+
+ intervals = [ ("year","years")
+ , ("month", "months")
+ , ("day","days")
+ , ("hour","hours")
+ , ("min","mins")
+ , ("sec","secs")
+ , ("usec","usecs")
+ ],
+
+ amPm = ("AM", "PM"),
+ dateTimeFmt = "%a %b %e %H:%M:%S %Z %Y",
+ dateFmt = "%m/%d/%y",
+ timeFmt = "%H:%M:%S",
+ time12Fmt = "%I:%M:%S %p"
+ }
+
+
+iso8601DateFormat :: Maybe String -> String
+iso8601DateFormat timeFmt =
+ "%Y-%m-%d" ++ case timeFmt of
+ Nothing -> "" -- normally, ISO-8601 just defines YYYY-MM-DD
+ Just fmt -> ' ' : fmt -- but we can add a time spec
+
+
+rfc822DateFormat :: String
+rfc822DateFormat = "%a, %_d %b %Y %H:%M:%S %Z"
diff --git a/libraries/base/System/Mem/StableName.hs b/libraries/base/System/Mem/StableName.hs
new file mode 100644
index 0000000000..12d2df14a9
--- /dev/null
+++ b/libraries/base/System/Mem/StableName.hs
@@ -0,0 +1,67 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Mem.StableName
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: StableName.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Giving an object a stable (GC-invariant) name.
+--
+-----------------------------------------------------------------------------
+
+module System.Mem.StableName
+ ( StableName {-a-} -- abstract, instance of Eq
+ , makeStableName -- :: a -> IO (StableName a)
+ , hashStableName -- :: StableName a -> Int
+ ) where
+
+import Prelude
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base ( Int(..) )
+import GHC.IOBase ( IO(..) )
+import GHC.Prim ( StableName#, makeStableName#
+ , eqStableName#, stableNameToInt# )
+
+-----------------------------------------------------------------------------
+-- Stable Names
+
+data StableName a = StableName (StableName# a)
+
+makeStableName :: a -> IO (StableName a)
+#if defined(__PARALLEL_HASKELL__)
+makeStableName a =
+ error "makeStableName not implemented in parallel Haskell"
+#else
+makeStableName a = IO $ \ s ->
+ case makeStableName# a s of (# s', sn #) -> (# s', StableName sn #)
+#endif
+
+hashStableName :: StableName a -> Int
+#if defined(__PARALLEL_HASKELL__)
+hashStableName (StableName sn) =
+ error "hashStableName not implemented in parallel Haskell"
+#else
+hashStableName (StableName sn) = I# (stableNameToInt# sn)
+#endif
+
+instance Eq (StableName a) where
+#if defined(__PARALLEL_HASKELL__)
+ (StableName sn1) == (StableName sn2) =
+ error "eqStableName not implemented in parallel Haskell"
+#else
+ (StableName sn1) == (StableName sn2) =
+ case eqStableName# sn1 sn2 of
+ 0# -> False
+ _ -> True
+#endif
+
+#endif /* __GLASGOW_HASKELL__ */
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE1(StableName,stableNameTc,"StableName")
diff --git a/libraries/base/System/Mem/Weak.hs b/libraries/base/System/Mem/Weak.hs
new file mode 100644
index 0000000000..09c095dfc8
--- /dev/null
+++ b/libraries/base/System/Mem/Weak.hs
@@ -0,0 +1,56 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Mem.Weak
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- $Id: Weak.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Weak references, weak pairs, weak pointers, and finalizers.
+--
+-----------------------------------------------------------------------------
+
+module System.Mem.Weak (
+ Weak, -- abstract
+ -- instance Eq (Weak v)
+
+ mkWeak, -- :: k -> v -> Maybe (IO ()) -> IO (Weak v)
+ deRefWeak, -- :: Weak v -> IO (Maybe v)
+ finalize, -- :: Weak v -> IO ()
+ -- replaceFinaliser -- :: Weak v -> IO () -> IO ()
+
+ mkWeakPtr, -- :: k -> Maybe (IO ()) -> IO (Weak k)
+ mkWeakPair, -- :: k -> v -> Maybe (IO ()) -> IO (Weak (k,v))
+ addFinalizer -- :: key -> IO () -> IO ()
+ ) where
+
+import Prelude
+
+#include "Dynamic.h"
+INSTANCE_TYPEABLE0(Weak,weakTc,"Weak")
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Base
+import GHC.IOBase
+import GHC.Weak
+
+deRefWeak :: Weak v -> IO (Maybe v)
+deRefWeak (Weak w) = IO $ \s ->
+ case deRefWeak# w s of
+ (# s1, flag, p #) -> case flag of
+ 0# -> (# s1, Nothing #)
+ _ -> (# s1, Just p #)
+
+mkWeakPair :: k -> v -> Maybe (IO ()) -> IO (Weak (k,v))
+mkWeakPair key val finalizer = mkWeak key (key,val) finalizer
+
+finalize :: Weak v -> IO ()
+finalize (Weak w) = IO $ \s ->
+ case finalizeWeak# w s of
+ (# s1, 0#, _ #) -> (# s1, () #) -- already dead, or no finaliser
+ (# s1, _, f #) -> f s1
+#endif
diff --git a/libraries/base/System/Random.hs b/libraries/base/System/Random.hs
new file mode 100644
index 0000000000..aa3ddf6005
--- /dev/null
+++ b/libraries/base/System/Random.hs
@@ -0,0 +1,279 @@
+-----------------------------------------------------------------------------
+--
+-- Module : System.Random
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Random.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Random numbers.
+--
+-----------------------------------------------------------------------------
+
+module System.Random
+ (
+ RandomGen(next, split)
+ , StdGen
+ , mkStdGen
+ , Random ( random, randomR,
+ randoms, randomRs,
+ randomIO, randomRIO )
+ , getStdRandom
+ , getStdGen
+ , setStdGen
+ , newStdGen
+ ) where
+
+-- The June 1988 (v31 #6) issue of the Communications of the ACM has an
+-- article by Pierre L'Ecuyer called, "Efficient and Portable Combined
+-- Random Number Generators". Here is the Portable Combined Generator of
+-- L'Ecuyer for 32-bit computers. It has a period of roughly 2.30584e18.
+
+-- Transliterator: Lennart Augustsson
+
+-- sof 1/99 - code brought (kicking and screaming) into the new Random
+-- world..
+
+import Prelude
+
+import System.CPUTime ( getCPUTime )
+import Data.Char ( isSpace, chr, ord )
+import System.IO.Unsafe ( unsafePerformIO )
+import Data.IORef
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Show ( showSignedInt, showSpace )
+import GHC.Read ( readDec )
+import GHC.IOBase ( unsafePerformIO, stToIO )
+import System.Time ( getClockTime, ClockTime(..) )
+#endif
+
+class RandomGen g where
+ next :: g -> (Int, g)
+ split :: g -> (g, g)
+
+
+data StdGen
+ = StdGen Int Int
+
+instance RandomGen StdGen where
+ next = stdNext
+ split = stdSplit
+
+#ifdef __GLASGOW_HASKELL__
+instance Show StdGen where
+ showsPrec p (StdGen s1 s2) =
+ showSignedInt p s1 .
+ showSpace .
+ showSignedInt p s2
+#endif
+
+#ifdef __HUGS__
+instance Show StdGen where
+ showsPrec p (StdGen s1 s2) =
+ showsPrec p s1 .
+ showChar ' ' .
+ showsPrec p s2
+#endif
+
+instance Read StdGen where
+ readsPrec _p = \ r ->
+ case try_read r of
+ r@[_] -> r
+ _ -> [stdFromString r] -- because it shouldn't ever fail.
+ where
+ try_read r = do
+ (s1, r1) <- readDec (dropWhile isSpace r)
+ (s2, r2) <- readDec (dropWhile isSpace r1)
+ return (StdGen s1 s2, r2)
+
+{-
+ If we cannot unravel the StdGen from a string, create
+ one based on the string given.
+-}
+stdFromString :: String -> (StdGen, String)
+stdFromString s = (mkStdGen num, rest)
+ where (cs, rest) = splitAt 6 s
+ num = foldl (\a x -> x + 3 * a) 1 (map ord cs)
+
+
+mkStdGen :: Int -> StdGen -- why not Integer ?
+mkStdGen s
+ | s < 0 = mkStdGen (-s)
+ | otherwise = StdGen (s1+1) (s2+1)
+ where
+ (q, s1) = s `divMod` 2147483562
+ s2 = q `mod` 2147483398
+
+createStdGen :: Integer -> StdGen
+createStdGen s
+ | s < 0 = createStdGen (-s)
+ | otherwise = StdGen (fromInteger (s1+1)) (fromInteger (s2+1))
+ where
+ (q, s1) = s `divMod` 2147483562
+ s2 = q `mod` 2147483398
+
+
+-- The class definition - see library report for details.
+
+class Random a where
+ -- Minimal complete definition: random and randomR
+ random :: RandomGen g => g -> (a, g)
+ randomR :: RandomGen g => (a,a) -> g -> (a,g)
+
+ randoms :: RandomGen g => g -> [a]
+ randoms g = x : randoms g' where (x,g') = random g
+
+ randomRs :: RandomGen g => (a,a) -> g -> [a]
+ randomRs ival g = x : randomRs ival g' where (x,g') = randomR ival g
+
+ randomIO :: IO a
+ randomIO = getStdRandom random
+
+ randomRIO :: (a,a) -> IO a
+ randomRIO range = getStdRandom (randomR range)
+
+
+instance Random Int where
+ randomR (a,b) g = randomIvalInteger (toInteger a, toInteger b) g
+ random g = randomR (minBound,maxBound) g
+
+instance Random Char where
+ randomR (a,b) g =
+ case (randomIvalInteger (toInteger (ord a), toInteger (ord b)) g) of
+ (x,g) -> (chr x, g)
+ random g = randomR (minBound,maxBound) g
+
+instance Random Bool where
+ randomR (a,b) g =
+ case (randomIvalInteger (toInteger (bool2Int a), toInteger (bool2Int b)) g) of
+ (x, g) -> (int2Bool x, g)
+ where
+ bool2Int False = 0
+ bool2Int True = 1
+
+ int2Bool 0 = False
+ int2Bool _ = True
+
+ random g = randomR (minBound,maxBound) g
+
+instance Random Integer where
+ randomR ival g = randomIvalInteger ival g
+ random g = randomR (toInteger (minBound::Int), toInteger (maxBound::Int)) g
+
+instance Random Double where
+ randomR ival g = randomIvalDouble ival id g
+ random g = randomR (0::Double,1) g
+
+-- hah, so you thought you were saving cycles by using Float?
+instance Random Float where
+ random g = randomIvalDouble (0::Double,1) realToFrac g
+ randomR (a,b) g = randomIvalDouble (realToFrac a, realToFrac b) realToFrac g
+
+#ifdef __GLASGOW_HASKELL__
+mkStdRNG :: Integer -> IO StdGen
+mkStdRNG o = do
+ ct <- getCPUTime
+ (TOD sec _) <- getClockTime
+ return (createStdGen (sec * 12345 + ct + o))
+#endif
+
+#ifdef __HUGS__
+mkStdRNG :: Integer -> IO StdGen
+mkStdRNG o = do
+ ct <- getCPUTime
+ return (createStdGen (ct + o))
+#endif
+
+randomIvalInteger :: (RandomGen g, Num a) => (Integer, Integer) -> g -> (a, g)
+randomIvalInteger (l,h) rng
+ | l > h = randomIvalInteger (h,l) rng
+ | otherwise = case (f n 1 rng) of (v, rng') -> (fromInteger (l + v `mod` k), rng')
+ where
+ k = h - l + 1
+ b = 2147483561
+ n = iLogBase b k
+
+ f 0 acc g = (acc, g)
+ f n acc g =
+ let
+ (x,g') = next g
+ in
+ f (n-1) (fromIntegral x + acc * b) g'
+
+randomIvalDouble :: (RandomGen g, Fractional a) => (Double, Double) -> (Double -> a) -> g -> (a, g)
+randomIvalDouble (l,h) fromDouble rng
+ | l > h = randomIvalDouble (h,l) fromDouble rng
+ | otherwise =
+ case (randomIvalInteger (toInteger (minBound::Int), toInteger (maxBound::Int)) rng) of
+ (x, rng') ->
+ let
+ scaled_x =
+ fromDouble ((l+h)/2) +
+ fromDouble ((h-l) / realToFrac intRange) *
+ fromIntegral (x::Int)
+ in
+ (scaled_x, rng')
+
+intRange :: Integer
+intRange = toInteger (maxBound::Int) - toInteger (minBound::Int)
+
+iLogBase :: Integer -> Integer -> Integer
+iLogBase b i = if i < b then 1 else 1 + iLogBase b (i `div` b)
+
+stdNext :: StdGen -> (Int, StdGen)
+stdNext (StdGen s1 s2) = (z', StdGen s1'' s2'')
+ where z' = if z < 1 then z + 2147483562 else z
+ z = s1'' - s2''
+
+ k = s1 `quot` 53668
+ s1' = 40014 * (s1 - k * 53668) - k * 12211
+ s1'' = if s1' < 0 then s1' + 2147483563 else s1'
+
+ k' = s2 `quot` 52774
+ s2' = 40692 * (s2 - k' * 52774) - k' * 3791
+ s2'' = if s2' < 0 then s2' + 2147483399 else s2'
+
+stdSplit :: StdGen -> (StdGen, StdGen)
+stdSplit std@(StdGen s1 s2)
+ = (left, right)
+ where
+ -- no statistical foundation for this!
+ left = StdGen new_s1 t2
+ right = StdGen t1 new_s2
+
+ new_s1 | s1 == 2147483562 = 1
+ | otherwise = s1 + 1
+
+ new_s2 | s2 == 1 = 2147483398
+ | otherwise = s2 - 1
+
+ StdGen t1 t2 = snd (next std)
+
+
+setStdGen :: StdGen -> IO ()
+setStdGen sgen = writeIORef theStdGen sgen
+
+getStdGen :: IO StdGen
+getStdGen = readIORef theStdGen
+
+theStdGen :: IORef StdGen
+theStdGen = unsafePerformIO (newIORef (createStdGen 0))
+
+newStdGen :: IO StdGen
+newStdGen = do
+ rng <- getStdGen
+ let (a,b) = split rng
+ setStdGen a
+ return b
+
+getStdRandom :: (StdGen -> (a,StdGen)) -> IO a
+getStdRandom f = do
+ rng <- getStdGen
+ let (v, new_rng) = f rng
+ setStdGen new_rng
+ return v
diff --git a/libraries/base/System/Time.hsc b/libraries/base/System/Time.hsc
new file mode 100644
index 0000000000..b8d79b4260
--- /dev/null
+++ b/libraries/base/System/Time.hsc
@@ -0,0 +1,619 @@
+{-# OPTIONS -optc-DNON_POSIX_SOURCE #-}
+-- JRS 010117: we had to say NON_POSIX_SOURCE to get the resulting .hc
+-- to compile on sparc-solaris. Blargh.
+-----------------------------------------------------------------------------
+--
+-- Module : System.Time
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Time.hsc,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- The standard Time library.
+--
+-----------------------------------------------------------------------------
+
+{-
+Haskell 98 Time of Day Library
+------------------------------
+
+The Time library provides standard functionality for clock times,
+including timezone information (i.e, the functionality of "time.h",
+adapted to the Haskell environment), It follows RFC 1129 in its use of
+Coordinated Universal Time (UTC).
+
+2000/06/17 <michael.weber@post.rwth-aachen.de>:
+RESTRICTIONS:
+ * min./max. time diff currently is restricted to
+ [minBound::Int, maxBound::Int]
+
+ * surely other restrictions wrt. min/max bounds
+
+
+NOTES:
+ * printing times
+
+ `showTime' (used in `instance Show ClockTime') always prints time
+ converted to the local timezone (even if it is taken from
+ `(toClockTime . toUTCTime)'), whereas `calendarTimeToString'
+ honors the tzone & tz fields and prints UTC or whatever timezone
+ is stored inside CalendarTime.
+
+ Maybe `showTime' should be changed to use UTC, since it would
+ better correspond to the actual representation of `ClockTime'
+ (can be done by replacing localtime(3) by gmtime(3)).
+
+
+BUGS:
+ * add proper handling of microsecs, currently, they're mostly
+ ignored
+
+ * `formatFOO' case of `%s' is currently broken...
+
+
+TODO:
+ * check for unusual date cases, like 1970/1/1 00:00h, and conversions
+ between different timezone's etc.
+
+ * check, what needs to be in the IO monad, the current situation
+ seems to be a bit inconsistent to me
+
+ * check whether `isDst = -1' works as expected on other arch's
+ (Solaris anyone?)
+
+ * add functions to parse strings to `CalendarTime' (some day...)
+
+ * implement padding capabilities ("%_", "%-") in `formatFOO'
+
+ * add rfc822 timezone (+0200 is CEST) representation ("%z") in `formatFOO'
+-}
+
+module System.Time
+ (
+ Month(..)
+ , Day(..)
+
+ , ClockTime(..) -- non-standard, lib. report gives this as abstract
+ -- instance Eq, Ord
+ -- instance Show (non-standard)
+
+ , getClockTime
+
+ , TimeDiff(..)
+ , noTimeDiff -- non-standard (but useful when constructing TimeDiff vals.)
+ , diffClockTimes
+ , addToClockTime
+
+ , normalizeTimeDiff -- non-standard
+ , timeDiffToString -- non-standard
+ , formatTimeDiff -- non-standard
+
+ , CalendarTime(..)
+ , toCalendarTime
+ , toUTCTime
+ , toClockTime
+ , calendarTimeToString
+ , formatCalendarTime
+
+ ) where
+
+#include "HsCore.h"
+
+import Prelude
+
+import Data.Ix
+import System.Locale
+import System.IO.Unsafe
+
+import Foreign
+import Foreign.C
+
+-- One way to partition and give name to chunks of a year and a week:
+
+data Month
+ = January | February | March | April
+ | May | June | July | August
+ | September | October | November | December
+ deriving (Eq, Ord, Enum, Bounded, Ix, Read, Show)
+
+data Day
+ = Sunday | Monday | Tuesday | Wednesday
+ | Thursday | Friday | Saturday
+ deriving (Eq, Ord, Enum, Bounded, Ix, Read, Show)
+
+-- @ClockTime@ is an abstract type, used for the internal clock time.
+-- Clock times may be compared, converted to strings, or converted to an
+-- external calendar time @CalendarTime@.
+
+data ClockTime = TOD Integer -- Seconds since 00:00:00 on 1 Jan 1970
+ Integer -- Picoseconds with the specified second
+ deriving (Eq, Ord)
+
+-- When a ClockTime is shown, it is converted to a CalendarTime in the current
+-- timezone and then printed. FIXME: This is arguably wrong, since we can't
+-- get the current timezone without being in the IO monad.
+
+instance Show ClockTime where
+ showsPrec _ t = showString (calendarTimeToString
+ (unsafePerformIO (toCalendarTime t)))
+
+{-
+@CalendarTime@ is a user-readable and manipulable
+representation of the internal $ClockTime$ type. The
+numeric fields have the following ranges.
+
+\begin{verbatim}
+Value Range Comments
+----- ----- --------
+
+year -maxInt .. maxInt [Pre-Gregorian dates are inaccurate]
+mon 0 .. 11 [Jan = 0, Dec = 11]
+day 1 .. 31
+hour 0 .. 23
+min 0 .. 59
+sec 0 .. 61 [Allows for two leap seconds]
+picosec 0 .. (10^12)-1 [This could be over-precise?]
+wday 0 .. 6 [Sunday = 0, Saturday = 6]
+yday 0 .. 365 [364 in non-Leap years]
+tz -43200 .. 43200 [Variation from UTC in seconds]
+\end{verbatim}
+
+The {\em tzname} field is the name of the time zone. The {\em isdst}
+field indicates whether Daylight Savings Time would be in effect.
+-}
+
+data CalendarTime
+ = CalendarTime {
+ ctYear :: Int,
+ ctMonth :: Month,
+ ctDay :: Int,
+ ctHour :: Int,
+ ctMin :: Int,
+ ctSec :: Int,
+ ctPicosec :: Integer,
+ ctWDay :: Day,
+ ctYDay :: Int,
+ ctTZName :: String,
+ ctTZ :: Int,
+ ctIsDST :: Bool
+ }
+ deriving (Eq,Ord,Read,Show)
+
+-- The @TimeDiff@ type records the difference between two clock times in
+-- a user-readable way.
+
+data TimeDiff
+ = TimeDiff {
+ tdYear :: Int,
+ tdMonth :: Int,
+ tdDay :: Int,
+ tdHour :: Int,
+ tdMin :: Int,
+ tdSec :: Int,
+ tdPicosec :: Integer -- not standard
+ }
+ deriving (Eq,Ord,Read,Show)
+
+noTimeDiff :: TimeDiff
+noTimeDiff = TimeDiff 0 0 0 0 0 0 0
+
+-- -----------------------------------------------------------------------------
+-- getClockTime returns the current time in its internal representation.
+
+#if HAVE_GETTIMEOFDAY
+getClockTime = do
+ allocaBytes (#const sizeof(struct timeval)) $ \ p_timeval -> do
+ throwErrnoIfMinus1_ "getClockTime" $ gettimeofday p_timeval nullPtr
+ sec <- (#peek struct timeval,tv_sec) p_timeval :: IO CLong
+ usec <- (#peek struct timeval,tv_usec) p_timeval :: IO CLong
+ return (TOD (fromIntegral sec) ((fromIntegral usec) * 1000))
+
+#elif HAVE_FTIME
+getClockTime = do
+ allocaBytes (#const sizeof(struct timeb)) $ \ p_timeb -> do
+ ftime p_timeb
+ sec <- (#peek struct timeb,time) p_timeb :: IO CTime
+ msec <- (#peek struct timeb,millitm) p_timeb :: IO CUShort
+ return (TOD (fromIntegral sec) (fromIntegral msec * 1000{-ToDo: correct???-}))
+
+#else /* use POSIX time() */
+getClockTime = do
+ secs <- time nullPtr -- can't fail, according to POSIX
+ return (TOD (fromIntegral secs) 0)
+
+#endif
+
+-- -----------------------------------------------------------------------------
+-- addToClockTime d t adds a time difference d and a
+-- clock time t to yield a new clock time. The difference d
+-- may be either positive or negative. diffClockTimes t1 t2 returns
+-- the difference between two clock times t1 and t2 as a TimeDiff.
+
+addToClockTime :: TimeDiff -> ClockTime -> ClockTime
+addToClockTime (TimeDiff year mon day hour min sec psec)
+ (TOD c_sec c_psec) =
+ let
+ sec_diff = toInteger sec +
+ 60 * toInteger min +
+ 3600 * toInteger hour +
+ 24 * 3600 * toInteger day
+ cal = toUTCTime (TOD (c_sec + sec_diff) (c_psec + psec))
+ -- FIXME! ^^^^
+ new_mon = fromEnum (ctMonth cal) + r_mon
+ (month', yr_diff)
+ | new_mon < 0 = (toEnum (12 + new_mon), (-1))
+ | new_mon > 11 = (toEnum (new_mon `mod` 12), 1)
+ | otherwise = (toEnum new_mon, 0)
+
+ (r_yr, r_mon) = mon `quotRem` 12
+
+ year' = ctYear cal + year + r_yr + yr_diff
+ in
+ toClockTime cal{ctMonth=month', ctYear=year'}
+
+diffClockTimes :: ClockTime -> ClockTime -> TimeDiff
+-- diffClockTimes is meant to be the dual to `addToClockTime'.
+-- If you want to have the TimeDiff properly splitted, use
+-- `normalizeTimeDiff' on this function's result
+--
+-- CAVEAT: see comment of normalizeTimeDiff
+diffClockTimes (TOD sa pa) (TOD sb pb) =
+ noTimeDiff{ tdSec = fromIntegral (sa - sb)
+ -- FIXME: can handle just 68 years...
+ , tdPicosec = pa - pb
+ }
+
+
+normalizeTimeDiff :: TimeDiff -> TimeDiff
+-- FIXME: handle psecs properly
+-- FIXME: ?should be called by formatTimeDiff automagically?
+--
+-- when applied to something coming out of `diffClockTimes', you loose
+-- the duality to `addToClockTime', since a year does not always have
+-- 365 days, etc.
+--
+-- apply this function as late as possible to prevent those "rounding"
+-- errors
+normalizeTimeDiff td =
+ let
+ rest0 = tdSec td
+ + 60 * (tdMin td
+ + 60 * (tdHour td
+ + 24 * (tdDay td
+ + 30 * (tdMonth td
+ + 365 * tdYear td))))
+
+ (diffYears, rest1) = rest0 `quotRem` (365 * 24 * 3600)
+ (diffMonths, rest2) = rest1 `quotRem` (30 * 24 * 3600)
+ (diffDays, rest3) = rest2 `quotRem` (24 * 3600)
+ (diffHours, rest4) = rest3 `quotRem` 3600
+ (diffMins, diffSecs) = rest4 `quotRem` 60
+ in
+ td{ tdYear = diffYears
+ , tdMonth = diffMonths
+ , tdDay = diffDays
+ , tdHour = diffHours
+ , tdMin = diffMins
+ , tdSec = diffSecs
+ }
+
+-- -----------------------------------------------------------------------------
+-- How do we deal with timezones on this architecture?
+
+-- The POSIX way to do it is through the global variable tzname[].
+-- But that's crap, so we do it The BSD Way if we can: namely use the
+-- tm_zone and tm_gmtoff fields of struct tm, if they're available.
+
+zone :: Ptr CTm -> IO (Ptr CChar)
+gmtoff :: Ptr CTm -> IO CLong
+#if HAVE_TM_ZONE
+zone x = (#peek struct tm,tm_zone) x
+gmtoff x = (#peek struct tm,tm_gmtoff) x
+
+#else /* ! HAVE_TM_ZONE */
+# if HAVE_TZNAME || defined(_WIN32)
+# if cygwin32_TARGET_OS
+# define tzname _tzname
+# endif
+# ifndef mingw32_TARGET_OS
+foreign label tzname :: Ptr (Ptr CChar)
+# else
+foreign import "ghcTimezone" unsafe timezone :: Ptr CLong
+foreign import "ghcTzname" unsafe tzname :: Ptr (Ptr CChar)
+# def inline long *ghcTimezone(void) { return &_timezone; }
+# def inline char **ghcTzname(void) { return _tzname; }
+# endif
+zone x = do
+ dst <- (#peek struct tm,tm_isdst) x
+ if dst then peekElemOff tzname 1 else peekElemOff tzname 0
+# else /* ! HAVE_TZNAME */
+-- We're in trouble. If you should end up here, please report this as a bug.
+# error "Don't know how to get at timezone name on your OS."
+# endif /* ! HAVE_TZNAME */
+
+-- Get the offset in secs from UTC, if (struct tm) doesn't supply it. */
+#if defined(mingw32_TARGET_OS) || defined(cygwin32_TARGET_OS)
+#define timezone _timezone
+#endif
+
+# if HAVE_ALTZONE
+foreign label altzone :: Ptr CTime
+foreign label timezone :: Ptr CTime
+gmtoff x = do
+ dst <- (#peek struct tm,tm_isdst) x
+ tz <- if dst then peek altzone else peek timezone
+ return (fromIntegral tz)
+# define GMTOFF(x) (((struct tm *)x)->tm_isdst ? altzone : timezone )
+# else /* ! HAVE_ALTZONE */
+-- Assume that DST offset is 1 hour ...
+gmtoff x = do
+ dst <- (#peek struct tm,tm_isdst) x
+ tz <- peek timezone
+ if dst then return (fromIntegral tz - 3600) else return tz
+# endif /* ! HAVE_ALTZONE */
+#endif /* ! HAVE_TM_ZONE */
+
+-- -----------------------------------------------------------------------------
+-- toCalendarTime t converts t to a local time, modified by
+-- the current timezone and daylight savings time settings. toUTCTime
+-- t converts t into UTC time. toClockTime l converts l into the
+-- corresponding internal ClockTime. The wday, yday, tzname, and isdst fields
+-- are ignored.
+
+
+toCalendarTime :: ClockTime -> IO CalendarTime
+toCalendarTime = clockToCalendarTime localtime False
+
+toUTCTime :: ClockTime -> CalendarTime
+toUTCTime = unsafePerformIO . clockToCalendarTime gmtime True
+
+-- ToDo: should be made thread safe, because localtime uses static storage,
+-- or use the localtime_r version.
+clockToCalendarTime :: (Ptr CTime -> IO (Ptr CTm)) -> Bool -> ClockTime
+ -> IO CalendarTime
+clockToCalendarTime fun is_utc (TOD secs psec) = do
+ withObject (fromIntegral secs :: CTime) $ \ p_timer -> do
+ p_tm <- fun p_timer -- can't fail, according to POSIX
+ sec <- (#peek struct tm,tm_sec ) p_tm :: IO CInt
+ min <- (#peek struct tm,tm_min ) p_tm :: IO CInt
+ hour <- (#peek struct tm,tm_hour ) p_tm :: IO CInt
+ mday <- (#peek struct tm,tm_mday ) p_tm :: IO CInt
+ mon <- (#peek struct tm,tm_mon ) p_tm :: IO CInt
+ year <- (#peek struct tm,tm_year ) p_tm :: IO CInt
+ wday <- (#peek struct tm,tm_wday ) p_tm :: IO CInt
+ yday <- (#peek struct tm,tm_yday ) p_tm :: IO CInt
+ isdst <- (#peek struct tm,tm_isdst) p_tm :: IO CInt
+ zone <- zone p_tm
+ tz <- gmtoff p_tm
+
+ tzname <- peekCString zone
+
+ let month | mon >= 0 && mon <= 11 = toEnum (fromIntegral mon)
+ | otherwise = error ("toCalendarTime: illegal month value: " ++ show mon)
+
+ return (CalendarTime
+ (1900 + fromIntegral year)
+ month
+ (fromIntegral mday)
+ (fromIntegral hour)
+ (fromIntegral min)
+ (fromIntegral sec)
+ psec
+ (toEnum (fromIntegral wday))
+ (fromIntegral yday)
+ (if is_utc then "UTC" else tzname)
+ (if is_utc then 0 else fromIntegral tz)
+ (if is_utc then False else isdst /= 0))
+
+
+toClockTime :: CalendarTime -> ClockTime
+toClockTime (CalendarTime year mon mday hour min sec psec
+ _wday _yday _tzname tz isdst) =
+
+ -- `isDst' causes the date to be wrong by one hour...
+ -- FIXME: check, whether this works on other arch's than Linux, too...
+ --
+ -- so we set it to (-1) (means `unknown') and let `mktime' determine
+ -- the real value...
+ let isDst = -1 :: CInt in -- if isdst then (1::Int) else 0
+
+ if psec < 0 || psec > 999999999999 then
+ error "Time.toClockTime: picoseconds out of range"
+ else if tz < -43200 || tz > 43200 then
+ error "Time.toClockTime: timezone offset out of range"
+ else
+ unsafePerformIO $ do
+ allocaBytes (#const sizeof(struct tm)) $ \ p_tm -> do
+ (#poke struct tm,tm_sec ) p_tm (fromIntegral sec :: CInt)
+ (#poke struct tm,tm_min ) p_tm (fromIntegral min :: CInt)
+ (#poke struct tm,tm_hour ) p_tm (fromIntegral hour :: CInt)
+ (#poke struct tm,tm_mday ) p_tm (fromIntegral mday :: CInt)
+ (#poke struct tm,tm_mon ) p_tm (fromIntegral (fromEnum mon) :: CInt)
+ (#poke struct tm,tm_year ) p_tm (fromIntegral year - 1900 :: CInt)
+ (#poke struct tm,tm_isdst) p_tm isDst
+ t <- throwIf (== -1) (\_ -> "Time.toClockTime: invalid input")
+ (mktime p_tm)
+ --
+ -- mktime expects its argument to be in the local timezone, but
+ -- toUTCTime makes UTC-encoded CalendarTime's ...
+ --
+ -- Since there is no any_tz_struct_tm-to-time_t conversion
+ -- function, we have to fake one... :-) If not in all, it works in
+ -- most cases (before, it was the other way round...)
+ --
+ -- Luckily, mktime tells us, what it *thinks* the timezone is, so,
+ -- to compensate, we add the timezone difference to mktime's
+ -- result.
+ --
+ gmtoff <- gmtoff p_tm
+ let res = fromIntegral t - tz + fromIntegral gmtoff
+ return (TOD (fromIntegral res) 0)
+
+-- -----------------------------------------------------------------------------
+-- Converting time values to strings.
+
+calendarTimeToString :: CalendarTime -> String
+calendarTimeToString = formatCalendarTime defaultTimeLocale "%c"
+
+formatCalendarTime :: TimeLocale -> String -> CalendarTime -> String
+formatCalendarTime l fmt (CalendarTime year mon day hour min sec _
+ wday yday tzname _ _) =
+ doFmt fmt
+ where doFmt ('%':'-':cs) = doFmt ('%':cs) -- padding not implemented
+ doFmt ('%':'_':cs) = doFmt ('%':cs) -- padding not implemented
+ doFmt ('%':c:cs) = decode c ++ doFmt cs
+ doFmt (c:cs) = c : doFmt cs
+ doFmt "" = ""
+
+ decode 'A' = fst (wDays l !! fromEnum wday) -- day of the week, full name
+ decode 'a' = snd (wDays l !! fromEnum wday) -- day of the week, abbrev.
+ decode 'B' = fst (months l !! fromEnum mon) -- month, full name
+ decode 'b' = snd (months l !! fromEnum mon) -- month, abbrev
+ decode 'h' = snd (months l !! fromEnum mon) -- ditto
+ decode 'C' = show2 (year `quot` 100) -- century
+ decode 'c' = doFmt (dateTimeFmt l) -- locale's data and time format.
+ decode 'D' = doFmt "%m/%d/%y"
+ decode 'd' = show2 day -- day of the month
+ decode 'e' = show2' day -- ditto, padded
+ decode 'H' = show2 hour -- hours, 24-hour clock, padded
+ decode 'I' = show2 (to12 hour) -- hours, 12-hour clock
+ decode 'j' = show3 yday -- day of the year
+ decode 'k' = show2' hour -- hours, 24-hour clock, no padding
+ decode 'l' = show2' (to12 hour) -- hours, 12-hour clock, no padding
+ decode 'M' = show2 min -- minutes
+ decode 'm' = show2 (fromEnum mon+1) -- numeric month
+ decode 'n' = "\n"
+ decode 'p' = (if hour < 12 then fst else snd) (amPm l) -- am or pm
+ decode 'R' = doFmt "%H:%M"
+ decode 'r' = doFmt (time12Fmt l)
+ decode 'T' = doFmt "%H:%M:%S"
+ decode 't' = "\t"
+ decode 'S' = show2 sec -- seconds
+ decode 's' = show2 sec -- number of secs since Epoch. (ToDo.)
+ decode 'U' = show2 ((yday + 7 - fromEnum wday) `div` 7) -- week number, starting on Sunday.
+ decode 'u' = show (let n = fromEnum wday in -- numeric day of the week (1=Monday, 7=Sunday)
+ if n == 0 then 7 else n)
+ decode 'V' = -- week number (as per ISO-8601.)
+ let (week, days) = -- [yep, I've always wanted to be able to display that too.]
+ (yday + 7 - if fromEnum wday > 0 then
+ fromEnum wday - 1 else 6) `divMod` 7
+ in show2 (if days >= 4 then
+ week+1
+ else if week == 0 then 53 else week)
+
+ decode 'W' = -- week number, weeks starting on monday
+ show2 ((yday + 7 - if fromEnum wday > 0 then
+ fromEnum wday - 1 else 6) `div` 7)
+ decode 'w' = show (fromEnum wday) -- numeric day of the week, weeks starting on Sunday.
+ decode 'X' = doFmt (timeFmt l) -- locale's preferred way of printing time.
+ decode 'x' = doFmt (dateFmt l) -- locale's preferred way of printing dates.
+ decode 'Y' = show year -- year, including century.
+ decode 'y' = show2 (year `rem` 100) -- year, within century.
+ decode 'Z' = tzname -- timezone name
+ decode '%' = "%"
+ decode c = [c]
+
+
+show2, show2', show3 :: Int -> String
+show2 x
+ | x' < 10 = '0': show x'
+ | otherwise = show x'
+ where x' = x `rem` 100
+
+show2' x
+ | x' < 10 = ' ': show x'
+ | otherwise = show x'
+ where x' = x `rem` 100
+
+show3 x = show (x `quot` 100) ++ show2 (x `rem` 100)
+ where x' = x `rem` 1000
+
+to12 :: Int -> Int
+to12 h = let h' = h `mod` 12 in if h' == 0 then 12 else h'
+
+-- Useful extensions for formatting TimeDiffs.
+
+timeDiffToString :: TimeDiff -> String
+timeDiffToString = formatTimeDiff defaultTimeLocale "%c"
+
+formatTimeDiff :: TimeLocale -> String -> TimeDiff -> String
+formatTimeDiff l fmt td@(TimeDiff year month day hour min sec _)
+ = doFmt fmt
+ where
+ doFmt "" = ""
+ doFmt ('%':'-':cs) = doFmt ('%':cs) -- padding not implemented
+ doFmt ('%':'_':cs) = doFmt ('%':cs) -- padding not implemented
+ doFmt ('%':c:cs) = decode c ++ doFmt cs
+ doFmt (c:cs) = c : doFmt cs
+
+ decode spec =
+ case spec of
+ 'B' -> fst (months l !! fromEnum month)
+ 'b' -> snd (months l !! fromEnum month)
+ 'h' -> snd (months l !! fromEnum month)
+ 'c' -> defaultTimeDiffFmt td
+ 'C' -> show2 (year `quot` 100)
+ 'D' -> doFmt "%m/%d/%y"
+ 'd' -> show2 day
+ 'e' -> show2' day
+ 'H' -> show2 hour
+ 'I' -> show2 (to12 hour)
+ 'k' -> show2' hour
+ 'l' -> show2' (to12 hour)
+ 'M' -> show2 min
+ 'm' -> show2 (fromEnum month + 1)
+ 'n' -> "\n"
+ 'p' -> (if hour < 12 then fst else snd) (amPm l)
+ 'R' -> doFmt "%H:%M"
+ 'r' -> doFmt (time12Fmt l)
+ 'T' -> doFmt "%H:%M:%S"
+ 't' -> "\t"
+ 'S' -> show2 sec
+ 's' -> show2 sec -- Implementation-dependent, sez the lib doc..
+ 'X' -> doFmt (timeFmt l)
+ 'x' -> doFmt (dateFmt l)
+ 'Y' -> show year
+ 'y' -> show2 (year `rem` 100)
+ '%' -> "%"
+ c -> [c]
+
+ defaultTimeDiffFmt (TimeDiff year month day hour min sec _) =
+ foldr (\ (v,s) rest ->
+ (if v /= 0
+ then show v ++ ' ':(addS v s)
+ ++ if null rest then "" else ", "
+ else "") ++ rest
+ )
+ ""
+ (zip [year, month, day, hour, min, sec] (intervals l))
+
+ addS v s = if abs v == 1 then fst s else snd s
+
+
+-- -----------------------------------------------------------------------------
+-- Foreign time interface (POSIX)
+
+type CTm = () -- struct tm
+
+foreign import unsafe localtime :: Ptr CTime -> IO (Ptr CTm)
+foreign import unsafe gmtime :: Ptr CTime -> IO (Ptr CTm)
+foreign import unsafe mktime :: Ptr CTm -> IO CTime
+foreign import unsafe time :: Ptr CTime -> IO CTime
+
+#if HAVE_GETTIMEOFDAY
+type CTimeVal = ()
+foreign import unsafe gettimeofday :: Ptr CTimeVal -> Ptr () -> IO CInt
+#endif
+
+#if HAVE_FTIME
+type CTimeB = ()
+#ifndef mingw32_TARGET_OS
+foreign import unsafe ftime :: Ptr CTimeB -> IO CInt
+#else
+foreign import unsafe ftime :: Ptr CTimeB -> IO ()
+#endif
+#endif
diff --git a/libraries/base/Text/Read.hs b/libraries/base/Text/Read.hs
new file mode 100644
index 0000000000..47813eb424
--- /dev/null
+++ b/libraries/base/Text/Read.hs
@@ -0,0 +1,32 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Text.Read
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Read.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Exiting the program.
+--
+-----------------------------------------------------------------------------
+
+module Text.Read (
+ ReadS, -- String -> Maybe (a,String)
+ Read(
+ readsPrec, -- :: Int -> ReadS a
+ readList -- :: ReadS [a]
+ ),
+ reads, -- :: (Read a) => ReadS a
+ read, -- :: (Read a) => String -> a
+ readParen, -- :: Bool -> ReadS a -> ReadS a
+ lex, -- :: ReadS String
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Read
+#endif
diff --git a/libraries/base/Text/Show.hs b/libraries/base/Text/Show.hs
new file mode 100644
index 0000000000..28294f1c55
--- /dev/null
+++ b/libraries/base/Text/Show.hs
@@ -0,0 +1,34 @@
+{-# OPTIONS -fno-implicit-prelude #-}
+-----------------------------------------------------------------------------
+--
+-- Module : Text.Show
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Show.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Exiting the program.
+--
+-----------------------------------------------------------------------------
+
+module Text.Show (
+ ShowS, -- String -> String
+ Show(
+ showsPrec, -- :: Int -> a -> ShowS
+ show, -- :: a -> String
+ showList -- :: [a] -> ShowS
+ ),
+ shows, -- :: (Show a) => a -> ShowS
+ showChar, -- :: Char -> ShowS
+ showString, -- :: String -> ShowS
+ showParen, -- :: Bool -> ShowS -> ShowS
+ ) where
+
+#ifdef __GLASGOW_HASKELL__
+import GHC.Show
+#endif
+
diff --git a/libraries/base/Text/Show/Functions.hs b/libraries/base/Text/Show/Functions.hs
new file mode 100644
index 0000000000..b246c44d30
--- /dev/null
+++ b/libraries/base/Text/Show/Functions.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------------------
+--
+-- Module : Text.Show.Functions
+-- Copyright : (c) The University of Glasgow 2001
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : portable
+--
+-- $Id: Functions.hs,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- Optional instance of Text.Show.Show for functions.
+--
+-----------------------------------------------------------------------------
+
+module Text.Show.Functions where
+
+import Prelude
+
+instance Show (a -> b) where
+ showsPrec _ _ = showString "<function>"
diff --git a/libraries/base/cbits/Makefile b/libraries/base/cbits/Makefile
new file mode 100644
index 0000000000..d1c450c52f
--- /dev/null
+++ b/libraries/base/cbits/Makefile
@@ -0,0 +1,20 @@
+# $Id: Makefile,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+
+TOP = ../../..
+include $(TOP)/mk/boilerplate.mk
+
+HSLIB = core
+IS_CBITS_LIB = YES
+
+SRC_CC_OPTS += -Wall -DCOMPILING_STDLIB -I../include -I../../../ghc/includes -I../../../ghc/rts
+
+ifeq "$(DLLized)" "YES"
+SRC_CC_OPTS += -dynamic
+endif
+
+# -----------------------------------------------------------------------------
+# Installation
+
+INSTALL_DATAS += lockFile.h
+
+include $(TOP)/mk/target.mk
diff --git a/libraries/base/cbits/errno.c b/libraries/base/cbits/errno.c
new file mode 100644
index 0000000000..0e2d71cbc2
--- /dev/null
+++ b/libraries/base/cbits/errno.c
@@ -0,0 +1,15 @@
+/*
+ * (c) The University of Glasgow, 2000-2001
+ *
+ * $Id: errno.c,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * GHC Error Number Conversion
+ */
+
+#include "HsCore.h"
+
+/* Raw errno */
+
+int *ghcErrno(void) {
+ return &errno;
+}
diff --git a/libraries/base/cbits/inputReady.c b/libraries/base/cbits/inputReady.c
new file mode 100644
index 0000000000..4cb9908617
--- /dev/null
+++ b/libraries/base/cbits/inputReady.c
@@ -0,0 +1,53 @@
+/*
+ * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
+ *
+ * $Id: inputReady.c,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * hReady Runtime Support
+ */
+
+/* select and supporting types is not */
+#ifndef _AIX
+#define NON_POSIX_SOURCE
+#endif
+
+#include "HsCore.h"
+
+/*
+ * inputReady(fd) checks to see whether input is available on the file
+ * descriptor 'fd'. Input meaning 'can I safely read at least a
+ * *character* from this file object without blocking?'
+ */
+int
+inputReady(int fd, int msecs)
+{
+ int maxfd, ready;
+#ifndef mingw32_TARGET_OS
+ fd_set rfd;
+ struct timeval tv;
+#endif
+
+#ifdef mingw32_TARGET_OS
+ return 1;
+#else
+ FD_ZERO(&rfd);
+ FD_SET(fd, &rfd);
+
+ /* select() will consider the descriptor set in the range of 0 to
+ * (maxfd-1)
+ */
+ maxfd = fd + 1;
+ tv.tv_sec = msecs / 1000;
+ tv.tv_usec = msecs % 1000;
+
+ while ((ready = select(maxfd, &rfd, NULL, NULL, &tv)) < 0 ) {
+ if (errno != EINTR ) {
+ return -1;
+ }
+ }
+
+ /* 1 => Input ready, 0 => not ready, -1 => error */
+ return (ready);
+
+#endif
+}
diff --git a/libraries/base/cbits/lockFile.c b/libraries/base/cbits/lockFile.c
new file mode 100644
index 0000000000..0ffad7d5ea
--- /dev/null
+++ b/libraries/base/cbits/lockFile.c
@@ -0,0 +1,128 @@
+/*
+ * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
+ *
+ * $Id: lockFile.c,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * stdin/stout/stderr Runtime Support
+ */
+
+#include "HsCore.h"
+
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 256
+#endif
+
+typedef struct {
+ dev_t device;
+ ino_t inode;
+ int fd;
+} Lock;
+
+static Lock readLock[FD_SETSIZE];
+static Lock writeLock[FD_SETSIZE];
+
+static int readLocks = 0;
+static int writeLocks = 0;
+
+int
+lockFile(int fd, int for_writing, int exclusive)
+{
+ struct stat sb;
+ int i;
+
+ while (fstat(fd, &sb) < 0) {
+ if (errno != EINTR) {
+#ifndef _WIN32
+ return -1;
+#else
+ /* fstat()ing socket fd's seems to fail with CRT's fstat(),
+ so let's just silently return and hope for the best..
+ */
+ return 0;
+#endif
+ }
+ }
+
+ if (for_writing) {
+ /* opening a file for writing, check to see whether
+ we don't have any read locks on it already.. */
+ for (i = 0; i < readLocks; i++) {
+ if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
+#ifndef __MINGW32__
+ return -1;
+#else
+ break;
+#endif
+ }
+ }
+ /* If we're determined that there is only a single
+ writer to the file, check to see whether the file
+ hasn't already been opened for writing..
+ */
+ if (exclusive) {
+ for (i = 0; i < writeLocks; i++) {
+ if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) {
+#ifndef __MINGW32__
+ return -1;
+#else
+ break;
+#endif
+ }
+ }
+ }
+ /* OK, everything is cool lock-wise, record it and leave. */
+ i = writeLocks++;
+ writeLock[i].device = sb.st_dev;
+ writeLock[i].inode = sb.st_ino;
+ writeLock[i].fd = fd;
+ return 0;
+ } else {
+ /* For reading, it's simpler - just check to see
+ that there's no-one writing to the underlying file. */
+ for (i = 0; i < writeLocks; i++) {
+ if (writeLock[i].inode == sb.st_ino && writeLock[i].device == sb.st_dev) {
+#ifndef __MINGW32__
+ return -1;
+#else
+ break;
+#endif
+ }
+ }
+ /* Fit in new entry, reusing an existing table entry, if possible. */
+ for (i = 0; i < readLocks; i++) {
+ if (readLock[i].inode == sb.st_ino && readLock[i].device == sb.st_dev) {
+ return 0;
+ }
+ }
+ i = readLocks++;
+ readLock[i].device = sb.st_dev;
+ readLock[i].inode = sb.st_ino;
+ readLock[i].fd = fd;
+ return 0;
+ }
+
+}
+
+int
+unlockFile(int fd)
+{
+ int i;
+
+ for (i = 0; i < readLocks; i++)
+ if (readLock[i].fd == fd) {
+ while (++i < readLocks)
+ readLock[i - 1] = readLock[i];
+ readLocks--;
+ return 0;
+ }
+
+ for (i = 0; i < writeLocks; i++)
+ if (writeLock[i].fd == fd) {
+ while (++i < writeLocks)
+ writeLock[i - 1] = writeLock[i];
+ writeLocks--;
+ return 0;
+ }
+ /* Signal that we did not find an entry */
+ return 1;
+}
diff --git a/libraries/base/cbits/system.c b/libraries/base/cbits/system.c
new file mode 100644
index 0000000000..289499bf26
--- /dev/null
+++ b/libraries/base/cbits/system.c
@@ -0,0 +1,87 @@
+/*
+ * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
+ *
+ * $Id: system.c,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * system Runtime Support
+ */
+
+/* The itimer stuff in this module is non-posix */
+#define NON_POSIX_SOURCE
+
+#include "HsCore.h"
+
+#if defined(mingw32_TARGET_OS)
+#include <windows.h>
+#endif
+
+HsInt
+systemCmd(HsAddr cmd)
+{
+#if defined(mingw32_TARGET_OS)
+ STARTUPINFO sInfo;
+ PROCESS_INFORMATION pInfo;
+ DWORD retCode;
+
+ sInfo.cb = sizeof(STARTUPINFO);
+ sInfo.lpReserved = NULL;
+ sInfo.lpReserved2 = NULL;
+ sInfo.cbReserved2 = 0;
+ sInfo.lpDesktop = NULL;
+ sInfo.lpTitle = NULL;
+ sInfo.dwFlags = 0;
+
+ if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo))
+ return -1;
+ WaitForSingleObject(pInfo.hProcess, INFINITE);
+ if (GetExitCodeProcess(pInfo.hProcess, &retCode) == 0) return -1;
+ CloseHandle(pInfo.hProcess);
+ CloseHandle(pInfo.hThread);
+ return retCode;
+#else
+ int pid;
+ int wstat;
+
+ switch(pid = fork()) {
+ case -1:
+ if (errno != EINTR) {
+ return -1;
+ }
+ case 0:
+ {
+#ifdef HAVE_SETITIMER
+ /* Reset the itimers in the child, so it doesn't get plagued
+ * by SIGVTALRM interrupts.
+ */
+ struct timeval tv_null = { 0, 0 };
+ struct itimerval itv;
+ itv.it_interval = tv_null;
+ itv.it_value = tv_null;
+ setitimer(ITIMER_REAL, &itv, NULL);
+ setitimer(ITIMER_VIRTUAL, &itv, NULL);
+ setitimer(ITIMER_PROF, &itv, NULL);
+#endif
+
+ /* the child */
+ execl("/bin/sh", "sh", "-c", cmd, NULL);
+ _exit(127);
+ }
+ }
+
+ while (waitpid(pid, &wstat, 0) < 0) {
+ if (errno != EINTR) {
+ return -1;
+ }
+ }
+
+ if (WIFEXITED(wstat))
+ return WEXITSTATUS(wstat);
+ else if (WIFSIGNALED(wstat)) {
+ errno = EINTR;
+ }
+ else {
+ /* This should never happen */
+ }
+ return -1;
+#endif
+}
diff --git a/libraries/base/cbits/writeError.c b/libraries/base/cbits/writeError.c
new file mode 100644
index 0000000000..9f1f1924fe
--- /dev/null
+++ b/libraries/base/cbits/writeError.c
@@ -0,0 +1,51 @@
+/*
+ * (c) The GRASP/AQUA Project, Glasgow University, 1998
+ *
+ * $Id: writeError.c,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * hPutStr Runtime Support
+ */
+
+/*
+Writing out error messages. This is done outside Haskell
+(i.e., no use of the IO implementation is made), since it
+might be in an unstable state (e.g., hClose stderr >> error "foo")
+
+(A secondary reason is that ``error'' is used by the IO
+implementation in one or two places.)
+
+*/
+
+#include "Rts.h"
+#include "RtsUtils.h"
+#include "HsCore.h"
+
+HsAddr
+addrOf_ErrorHdrHook(void)
+{
+ return &ErrorHdrHook;
+}
+
+void
+writeErrString__ (HsAddr msg_hdr, HsAddr msg, HsInt len)
+{
+ int count = 0;
+ char* p = (char*)msg;
+ char nl = '\n';
+
+ resetNonBlockingFd(2);
+
+ /* Print error msg header */
+ if (msg_hdr) {
+ ((void (*)(int))msg_hdr)(2/*stderr*/);
+ }
+
+ while ( (count = write(2,p,len)) < len) {
+ if (errno != EINTR ) {
+ return;
+ }
+ len -= count;
+ p += count;
+ }
+ write(2, &nl, 1);
+}
diff --git a/libraries/base/doc/libraries.sgml b/libraries/base/doc/libraries.sgml
new file mode 100644
index 0000000000..75e2b8e6fc
--- /dev/null
+++ b/libraries/base/doc/libraries.sgml
@@ -0,0 +1,1156 @@
+<!DOCTYPE ARTICLE PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
+
+<article id="libraries">
+ <artheader>
+ <title>Haskell Libraries</title>
+ <orgname>The Haskell Libraries Mailing List</orgname>
+ <address><email>libraries@haskell.org</email></address>
+ </artheader>
+
+ <sect1 id="introduction">
+ <title>Introduction</title>
+
+ <para>This document consistutes part of a proposal for an
+ extension to the <ulink
+ url="http://www.haskell.org/onlinereport/">Haskell 98</ulink>
+ language. The full proposal has several parts: </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>A modest language extension to Haskell 98 that adds the
+ character <quote>.</quote> to the lexical syntax for a module
+ name, allowing a hierarchical module namespace where a module
+ name is a sequence of components separated by periods.</para>
+ </listitem>
+ <listitem>
+ <para>An allocation of the new module namespace to existing
+ and non-existent libraries, people, organisations, and local
+ use.</para>
+ </listitem>
+ <listitem>
+ <para>A policy and procedure for allocating new parts of the
+ namespace.</para>
+ </listitem>
+ <listitem>
+ <para>A set of libraries which are under the control of the
+ community, have reference implementations kept in a standard
+ place, and conform to a set of guidelines and policies set out
+ in this document. We shall call this set of libraries the
+ <firstterm>core libraries</firstterm>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>In addition, this document also describes:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Guidelines and conventions for organising the
+ hierarchy.</para>
+ </listitem>
+ <listitem>
+ <para>Our policy with respect to the design and evolution of
+ library APIs, versioning of library APIs, and maintenance of
+ the reference implementation.</para>
+ </listitem>
+ <listitem>
+ <para>A set of conventions for coding style and portability
+ within the core libraries.</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1 id="contributing">
+ <title>How to contribute</title>
+
+ <para>This project is driven by the Haskell community, so
+ contributions of all kinds are welcome. The first step is to join
+ the <ulink
+ url="http://www.haskell.org/mailman/listinfo/libraries">Haskell
+ libraries mailing list</ulink>, and maybe <ulink
+ url="http://www.haskell.org/pipermail/libraries/">browse the list
+ archives</ulink>. Some of the ways you can contribute are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>By donating code: for libraries in the core set which
+ don't yet have a reference implementation, or for new
+ contributions to the core set, code is always welcome. Code
+ that conforms to the style guidelines (which aren't very
+ strict, see <xref linkend="conventions">) and comes with
+ documentation (<xref linkend="documentation">) and a test
+ suite (<xref linkend="testing">) is better, but these aren't
+ essential. As a library progresses through the stability
+ scale (<xref linkend="stability">) these things become more
+ important, but for an experimental library we're not going to
+ worry too much about this stuff.</para>
+ </listitem>
+ <listitem>
+ <para>By porting code for an existing library to a new
+ compiler or architecture. A library is classed as portable if
+ it should be available regardless of which compiler/platform
+ combination you're using; however, many libraries are
+ non-portable for one reason or another (see <xref
+ linkend="portability">, and broadening the scope of these
+ libraries is always welcome.</para>
+ </listitem>
+ <listitem>
+ <para>Become a library maintainer: if you have a particular
+ interest in and/or knowledge about a certain library, and have
+ the time to spare, and the library in question doesn't already
+ have a maintainer, then you may be a suitable maintainer for
+ the library. The responsibilities of library maintainers are
+ given in <xref linkend="maintainership">. </para>
+ </listitem>
+ <listitem>
+ <para>Participating in the design process for new libraries,
+ and suggesting improvements to existing libraries. Everyone
+ on the <ulink
+ url="http://www.haskell.org/mailman/listinfo/libraries">Haskell
+ libraries mailing list</ulink> is invited to
+ participate in the design process, so get involved!</para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1 id="layout">
+ <title>The hierarchy layout</title>
+
+ <para>We first classify each node in the hierarchy according to
+ one of the following terms:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>Allocated</term>
+ <listitem>
+ <para>Nodes in the hierarchy can be allocated to a library
+ (whether the library actually exists or not). The currently
+ allocated nodes are specified in <xref
+ linkend="hierarchy">.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>User</term>
+ <listitem>
+ <para>The <literal>User</literal> hierarchy is reserved for
+ users: a user may always use the portion of the hierarchy
+ which is formed from his/her email address as follows:
+ replace the <literal>@</literal> by a <literal>.</literal>,
+ reverse the order of the components, capitalise the first
+ letter of each component, and prepend
+ <literal>User.</literal>. For example,
+ <literal>simonmar@microsoft.com</literal> becomes
+ <literal>User.Com.Microsoft.Simonmar</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Organisation</term>
+ <listitem>
+ <para>The <literal>Org</literal> hierarchy is reserved for
+ organisations. Any organisation with a DNS domain name owns
+ a unique space in the hierarchy formed by reversing the
+ components of the domain, capitalising the first character
+ of each component, and prepending
+ <literal>Org.</literal>. <emphasis>ToDo: I don't like this
+ very much, any better ideas?</emphasis></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Local</term>
+ <listitem>
+ <para>The <literal>Local</literal> hierarchy is reserved for
+ libraries which are local to the current site. Libraries
+ which are to be distributed outside the current site should
+ not be placed in the <literal>Local</literal>
+ hierarchy.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Top-level</term>
+ <listitem>
+ <para>All top-level names (i.e. module names that don't
+ contain a <quote><literal>.</literal></quote>) that are
+ otherwise unallocated, are available for use by the program.
+ Note that for compabibility with Haskell 98, some modules in
+ this namespace are reserved
+ (eg. <literal>Directory</literal>, <literal>IO</literal>,
+ <literal>Time</literal> etc.).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Unallocated</term>
+ <listitem>
+ <para>Any node which doesn't belong to any of the above
+ categories is currently unallocated, and is not available
+ for use.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>A node in the hierarchy may be both a specific library and a
+ parent node for a number of child nodes. For example,
+ <literal>Foreign</literal> is a library, and so is
+ <literal>Foreign.Ptr</literal>.</para>
+
+ <sect2 id="hierarchy-design-guidelines">
+ <title>Hierarchy design guidelines</title>
+ <para></para>
+ </sect2>
+
+ <sect2 id="module-naming-convention">
+ <title>Module Naming Conventions</title>
+ <para></para>
+ </sect2>
+
+ <sect2 id="hierarchy">
+ <title>The hierarchy</title>
+
+ <para>The currently allocated top-level names are:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>Prelude</literal></term>
+ <listitem>
+ <para>Haskell98 Prelude (mostly just re-exports other
+ parts of the tree).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Control</literal></term>
+ <listitem>
+ <para> Libraries which provide functions, types or classes
+ whose purpose is primarily to express control
+ structure.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Data</literal></term>
+ <listitem>
+ <para>Libraries which provide data types, operations over
+ data types, or type classes, except for libraries for
+ which one of the other more specific categories is
+ appropriate.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Database</literal></term>
+ <listitem>
+ <para>Libraries for providing access to or operations for
+ building databases.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Debug</literal></term>
+ <listitem>
+ <para>Support for debugging Haskell programs.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Edison</literal></term>
+ <listitem>
+ <para>The Edison data structure library.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>FileFormat</literal></term>
+ <listitem>
+ <para>Support for reading and/or writing various file
+ formats (except: programming language source code which
+ lives in <literal>Language</literal>, database formats
+ which live in <literal>Database</literal>, and textual
+ file formats which are catered for in
+ <literal>Text</literal>).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Foreign</literal></term>
+ <listitem>
+ <para>Interaction with code written in a foreign
+ programming language.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Graphics</literal></term>
+ <listitem>
+ <para>Libraries for producing graphics or providing
+ graphical user interfaces.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Language</literal></term>
+ <listitem>
+ <para>Libraries for operating on or generating source code
+ in various programming languages, including parsers,
+ pretty printers, abstract syntax definitions etc.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Local</literal></term>
+ <listitem>
+ <para>Available for site-local use.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Numeric</literal></term>
+ <listitem>
+ <para>Functions and classes which provide operations over
+ numeric data.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Network</literal></term>
+ <listitem>
+ <para>Libraries for communicating over a network,
+ including implementations of network protocols.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Org</literal></term>
+ <listitem>
+ <para>Allocated to organisations on a domain-name
+ basis (see <xref linkend="layout">).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>System</literal></term>
+ <listitem>
+ <para>Libraries for communication with the system on which
+ the Haskell program is running (including the runtime
+ system).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Text</literal></term>
+ <listitem>
+ <para>Libraries for parsing and generating data in a
+ textual format (including structured textual formats such
+ as XML, HTML, but not including programming language
+ source, which lives in Language).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>GHC</literal></term>
+ <listitem>
+ <para>Libraries specific to the GHC/GHCi system.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>NHC</literal></term>
+ <listitem>
+ <para>Libraries specific to the NHC compiler.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>Hugs</literal></term>
+ <listitem>
+ <para>Libraries specific to the Hugs system.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>User</literal></term>
+ <listitem>
+ <para>Allocated to individual users, using email
+ addresses (see <xref linkend="layout">).</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+ </sect1>
+
+ <sect1 id="licensing">
+ <title>Licensing</title>
+
+ <para>Following some discussion on the mailing list related to how
+ we should license the libraries, the viewpoint that was least
+ offensive to all involved seems to be the following:</para>
+
+ <para>We wish to accomodate source code from different
+ contributors, and with different licenses. However, a library of
+ modules where each module is released under a different license,
+ and where the dependencies between modules aren't clear, isn't
+ workable (it's too hard for a user of the library to tell whether
+ they're violating the terms of the each license or not).</para>
+
+ <para>So the solution is as follows: code under different licenses
+ will be clearly separate in the repository (i.e. in separate
+ subdirectories), and compilers are expected to present packages of
+ modules where all modules in a package fall under the same
+ license, and where the dependencies between packages are
+ clear.</para>
+
+ <para>It was decided that certain essential functionality should
+ be available under a BSD style license. Hence, the BSD part of
+ the repository will contain implementations of at least the
+ following modules: <literal>Prelude</literal>,
+ <literal>Foreign</literal>, <emphasis>ToDo: what
+ else?</emphasis>.</para>
+
+ <para><emphasis>ToDo: include a prototype BSD license
+ here</emphasis>.</para>
+ </sect1>
+
+ <sect1 id="versioning">
+ <title>Versioning</title>
+ <para></para>
+ </sect1>
+
+ <sect1 id="stability">
+ <title>Library Stability</title>
+
+ <para>The stability of a library relates primarily to its API.
+ Stability provides an indication of how often the API is likely to
+ change (or whether it may even go away entirely).</para>
+
+ <para>The stability scale is also a measure of how strictly the
+ conventions in this document are applied to the library: an
+ experimental library isn't subject to any restrictions regarding
+ coding style and documentation, but a stable library is expected
+ to adhere to the guidelines, and come with full documentation and
+ tests.</para>
+
+ <para>To help with the stability issue, library maintainers are
+ allowed to mark functions, types or classes as
+ <firstterm>deprecated</firstterm><footnote><para>Compilers may have
+ extra support for warning about the use of a deprecated feature, for
+ example GHC's <literal>DEPRECATED</literal> pragma.</para>
+ </footnote>, which means simply that the
+ feature will be removed at a later date. Just how long it will
+ stick around for depends on the stability category of the library
+ (see below). A feature is marked as deprecated in the
+ documentation for the library, and optionally in an
+ implementation-dependent way which enables the system to warn
+ about the use of deprecated features.</para>
+
+ <para>The current stability categories are:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><firstterm>experimental</firstterm></term>
+ <listitem>
+ <para>An experimental library is unrestricted in terms of
+ API changes: the API may change between minor revisions and
+ there is no requirement to retain old interfaces for
+ compatibility. Documentation and tests aren't required for
+ an experimental library.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><firstterm>provisional</firstterm></term>
+ <listitem>
+ <para>A provisional library is moving towards stability, and
+ the rate of change of the API is slower. API changes
+ between minor revisions must be accompanied by deprecated
+ versions of the old features where possible. API changes
+ between major versions are unrestricted. The library should
+ come with at least rudimentary documentation.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><firstterm>stable</firstterm></term>
+ <listitem>
+ <para>A stable library has an essentially fixed API.
+ Additions to the API may be made for a minor release,
+ deprecated features must be retained for at least one major
+ revision, and small changes only may be made to the existing
+ API semantics for a major revision. A stable library is
+ expected to include full documentation and tests.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect1>
+
+ <sect1 id="portability">
+ <title>Portability Considerations</title>
+
+ <para>The portability status of a library affects under which
+ platforms and compilers the library will be available on. Haskell
+ implementations are expected to provide all of the portable core
+ libraries, and those non-portable core libraries which are
+ appropriate for that particular platform/compiler
+ implementation.</para>
+
+ <para>The precise meaning of the terms portable and non-portable
+ for our purposes are given below:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><firstterm>Portable</firstterm></term>
+ <listitem>
+ <para>A portable library may use only Haskell 98 features
+ plus approved extensions (see <xref linkend="portability">),
+ and may not use any platform-specific features. It may make
+ use of other portable libraries only.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><firstterm>Non-portable</firstterm></term>
+ <listitem>
+ <para>A non-portable library may be non-portable for one or
+ more of the following reasons:</para>
+ <variablelist>
+ <varlistentry>
+ <term><firstterm>Requires extensions</firstterm></term>
+ <listitem>
+ <para>A library which uses non-approved language
+ extensions.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><firstterm>Requires nonportable libraries</firstterm></term>
+ <listitem>
+ <para>A library which depends (directly or indirectly)
+ on other non-portable libraries.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><firstterm>OS-specific</firstterm></term>
+ <term><firstterm>Platform-specific</firstterm></term>
+ <listitem>
+ <para>A library which depends on features or APIs
+ particular to a certain OS or platform is non-portable
+ for that reason.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect1>
+
+ <sect1 id="maintainership">
+ <title>Library Maintainers</title>
+
+ <para>This is a collaborative project, so we like to devolve
+ control of the design and implementation of libraries to those
+ with an interest or appropriate expertise (or maybe just the
+ time!). A maintainer isn't necessarily a single person - for
+ example, the listed maintainer for most of the core libraries is
+ <email>libraries@haskell.org</email>, indicating that the library
+ is under the control of the community as a whole. The maintainer
+ for the <literal>Foreign</literal> hierarchy is
+ <email>ffi@haskell.org</email>, the mailing list for discussion of
+ the Haskell FFI standard.</para>
+
+ <para>The responsibilities of a library maintainer include:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Most importantly: act as a single point of contact for
+ issues relating to the library API and its
+ implementation.</para>
+ </listitem>
+ <listitem>
+ <para>Manage any discussion related to the library (which can
+ take place on <email>libraries.haskell.org</email> if
+ necessary), and summarise the results. Make final decisions,
+ and implement them.</para>
+ </listitem>
+ <listitem>
+ <para>Maintain the implementation, including: fixing bugs,
+ updating to keep up with changes in other libraries, porting
+ to new compilers/platforms, and integrating code from other
+ contributors. The maintainer is expected to be the only
+ person/group to make functional changes to the source code
+ (non-functional or trivial changes don't count).</para>
+ </listitem>
+ <listitem>
+ <para>Maintain/write the documentation and tests.</para>
+ </listitem>
+ <listitem>
+ <para>If you can't maintain the library any more for whatever
+ reason, tell <email>libraries@haskell.org</email> and we'll
+ revert the maintainer status of the library to the
+ default.</para>
+ </listitem>
+ </itemizedlist>
+
+ <sect2 id="core-team">
+ <title>The Core Team</title>
+
+ <para>The core team is responsible for making final decisions
+ about the project as a whole and resolving disputes where
+ necessary. We expect that needing to invoke the core team will
+ be a rare occurrence.</para>
+
+ <para>The core team is also responsible for approving
+ maintainership requests.</para>
+
+ <para>Currently, the core team consists of one person from each
+ of the compiler camps, and these are also the people that will
+ primarily be maintaining the library framework for their
+ respective compiler projects:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Simon Marlow
+ <email>simonmar@microsoft.com</email> (GHC representative)</para>
+ </listitem>
+ <listitem>
+ <para>Malcolm Wallace
+ <email>Malcolm.Wallace@cs.york.ac.uk</email> (NHC representative)</para>
+ </listitem>
+ <listitem>
+ <para>Andy Gill
+ <email>andy@galconn.com</email> (Hugs representative)</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="documentation">
+ <title>Documentation</title>
+ <para></para>
+ </sect1>
+
+ <sect1 id="testing">
+ <title>Testing</title>
+ <para></para>
+ </sect1>
+
+ <sect1 id="Migration-path">
+ <title>Migration path</title>
+
+ <para>How compatible will a compiler using the new libraries be
+ with code written for Haskell 98 or older library systems (such as
+ the <literal>hslibs</literal> suite and GHC's package system), and
+ for how long will compatibility be maintained?</para>
+
+ <para>Our current plan for GHC is as follows: by default, with the
+ <option>-fglasgow-exts</option> flag, you'll get access to the
+ core libraries. Compatibility with Haskell 98 code will be
+ maintained using a separate package of wrappers presenting
+ interfaces for the Haskell 98 libraries (<literal>IO</literal>,
+ <literal>Ratio</literal>, <literal>Directory</literal>, etc.).
+ The Haskell 98 compatibility package will be enabled by default,
+ but we plan to add an option to disable it if necessary. For code
+ that uses <literal>-package lang</literal>, we could also provide
+ a compatibility wrapper package (so <literal>-package
+ lang</literal> will continue to work as before and present the
+ same library interfaces), but this may prove too much work to
+ maintain - we haven't decided whether to do this or not. It is
+ unlikely that compatibility wrappers for any of the other
+ <literal>hslibs</literal> packages will be provided.</para>
+ </sect1>
+
+ <sect1 id="conventions">
+ <title>Programming Conventions</title>
+
+ <sect2 id="module-header">
+ <title>Standard Module Header</title> <para>The following module
+ header will be used for all core libraries, and we recommend
+ using it for library source code in general:</para>
+
+<programlisting>
+-----------------------------------------------------------------------------
+--
+-- Module : <replaceable>module</replaceable>
+-- Copyright : (c) <replaceable>author</replaceable> <replaceable>year</replaceable>
+-- License : <replaceable>license</replaceable>
+--
+-- Maintainer : libraries@haskell.org | <replaceable>email-address</replaceable>
+-- Stability : experimental | provisional | stable
+-- Portability : portable | non-portable (<replaceable>reason(s)</replaceable>)
+--
+-- $Id: libraries.sgml,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+--
+-- <replaceable>Description</replaceable>
+-----------------------------------------------------------------------------
+</programlisting>
+
+ <para>where:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>$Id: libraries.sgml,v 1.1 2001/06/28 14:15:04 simonmar Exp $</literal></term>
+ <listitem>
+ <para>is optional, but usually included if the module is
+ under CVS or RCS control.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>module</replaceable></term>
+ <listitem>
+ <para>is the fully qualified module name of the
+ module</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>author</replaceable>/<replaceable>year</replaceable></term>
+ <listitem>
+ <para>Is the primary author and copyright holder of the
+ module, and the year in which copyright is claimed.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>license</replaceable></term>
+ <listitem>
+ <para>Specifies the license on the file (see <xref
+ linkend="licensing">).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>email-address</replaceable></term>
+ <listitem>
+ <para>The email address of the maintainer, or maintainers,
+ of the library (see <xref linkend="maintainership">).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>reason(s)</replaceable></term>
+ <listitem>
+ <para>The reasons for non-portability must be listed (see
+ <xref linkend="portability">).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>description</replaceable></term>
+ <listitem>
+ <para>A short description of the module.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect2>
+
+ <sect2 id="naming-conventions">
+ <title>Naming Conventions</title>
+
+ <para>These naming conventions are pulled straight from the
+ <literal>hslibs</literal> documentation. They were formed after
+ lengthy discussions and are heavily based on an initial
+ suggestion from Marcin Kowalczyk
+ <email>qrczak@knm.org.pl</email>.</para>
+
+ <para>Note that the conventions are not mutually exclusive,
+ e.g. should the function creating a set from a list of elements
+ have the name <Literal>set</Literal> or
+ <Literal>listToSet</Literal>? (Alas, it currently has neither
+ name.)</para>
+
+ <para> The following nomenclature is used: Pure,
+ i.e. non-monadic functions are simply called, well,
+ <emphasis>functions</emphasis>. Monadic functions,
+ i.e. functions having a type <Literal>... -&#62; m a</Literal>
+ for some Monad <Literal>m</Literal> are called
+ <emphasis>actions</emphasis>.</para>
+
+ <sect3 id="sec-library-module-names">
+ <title>Module names</title>
+ <itemizedlist>
+ <listitem>
+ <para>A module defining a data type or type class
+ <replaceable>X</replaceable> has the itself the name
+ <replaceable>X</replaceable>, e.g.
+ <literal>StablePtr</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>A module which re-exports the modules in a subtree
+ of the hierarchy has the same name as the root of that
+ subtree, eg. <literal>Foreign</literal> re-exports
+ <literal>Foreign.Ptr</literal>,
+ <literal>Foreign.MarshalUtils</literal> etc.</para>
+ </listitem>
+
+ <listitem>
+ <para>If a subtree of the hierarchy contains several
+ modules which provide similar functionality (eg. there are
+ several pretty-printing libraries under
+ <literal>Text.PrettyPrinter</literal>), then the module at
+ the root of the subtree generally re-exports just
+ <emphasis>one</emphasis> of the modules in the subtree
+ (possibly the most popular or commonly-used
+ alternative).</para>
+ </listitem>
+
+ <listitem>
+ <para>In Haskell you sometimes publish
+ <emphasis>two</emphasis> interfaces to your libraries; one
+ for users, and one for library writers or advanced users
+ who might want to extend things. Typically the advanced
+ users need to be able to see past certain
+ abstractions.</para>
+
+ <para>The current proposal is for a module named
+ <literal>M</literal>, the <quote>advanced</quote> version
+ would be named <literal>M.Internals</literal>. eg.</para>
+
+<programlisting>
+import Text.Html -- The library
+import Text.Html.Internals -- The non-abstract library (for building other libs)
+</programlisting>
+ </listitem>
+
+ </itemizedlist>
+ </sect3>
+
+ <sect3 id="sec-library-constructor-names">
+ <title>Constructor names</title>
+ <indexterm><primary>Constructor names</primary></indexterm>
+
+ <itemizedlist>
+ <listitem>
+ <para>Empty values of type <replaceable>X</replaceable>
+ have the name <Literal>empty<replaceable>X</replaceable></Literal>,
+ e.g. <literal>emptySet</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Actions creating a new empty value of type
+ <replaceable>X</replaceable> have the name
+ <literal>newEmpty<replaceable>X</replaceable></literal>,
+ e.g. <literal>newEmptyMVar</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Functions creating an arbitrary value of type
+ <replaceable>X</replaceable> have the name
+ <replaceable>X</replaceable> itself (with the first letter
+ downcased),
+ e.g. <literal>array</literal>. (<emphasis>TODO</emphasis>:
+ This often collides with <literal>xToY</literal>
+ convention, how should this be resolved?)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Actions creating new values arbitrary values of type
+ <replaceable>X</replaceable> have the name
+ <literal>new<replaceable>X</replaceable></literal>,
+ e.g. <literal>newIORef</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3 id="sec-library-accessor-names">
+ <title>Accessor names</title>
+ <indexterm><primary>Accessor names</primary></indexterm>
+
+ <itemizedlist>
+ <listitem>
+ <para>Functions getting an attribute of a value or a part
+ of it have the name of the attribute itself,
+ e.g. <literal>length</literal>, <literal>bounds</literal>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para> Actions accessing some kind of reference or state
+ have the name
+ <literal>get<replaceable>X</replaceable></literal>, where
+ <replaceable>X</replaceable> is the type of the contents
+ or the name of the part being accessed,
+ e.g. <literal>getChar</literal>,
+ <literal>getEnv</literal>. An alternative naming scheme is
+ <literal>read<replaceable>Y</replaceable></literal>,
+ where <replaceable>Y</replaceable> is the type of the
+ reference or container, e.g. <literal>readIORef</literal>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Functions or actions getting a value via a
+ pointer-like type <replaceable>X</replaceable> should be
+ named
+ <literal>deRef<replaceable>X</replaceable></literal>,
+ e.g. <literal>deRefStablePtr</literal>,
+ <literal>deRefWeak</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3 id="sec-library-modifier-names">
+ <title>Modifier names</title>
+ <indexterm><primary>Modifier names</primary></indexterm>
+
+ <itemizedlist>
+ <listitem>
+ <para>Functions returning a value with attribute
+ <replaceable>X</replaceable> set to a new value should be
+ named
+ <literal>set<replaceable>X</replaceable></literal>. (<emphasis>TODO</emphasis>:
+ Add Examples.)</para>
+ </listitem>
+
+ <listitem>
+ <para> Actions setting some kind of reference or state
+ have the name
+ <literal>put<replaceable>X</replaceable></literal>, where
+ <replaceable>X</replaceable> is the type of the contents
+ or the name of the part being accessed,
+ e.g. <literal>putChar</literal>. An alternative naming
+ scheme is
+ <literal>write<replaceable>Y</replaceable></literal>,
+ where <replaceable>X</replaceable> is the type of the
+ reference or container,
+ e.g. <literal>writeIORef</literal>. </para></listitem>
+
+ <listitem>
+ <para> Actions in the <literal>IO</literal> monad setting
+ some global state <replaceable>X</replaceable> are
+ traditionally named <literal>setX</literal>, too, although
+ <literal>put<replaceable>X</replaceable></literal> would
+ be more appropriate,
+ e.g. <literal>setReadlineName</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para> Actions modifying a container
+ <replaceable>X</replaceable> by a function of type
+ <literal>a -> a</literal> have the name
+ <literal>modify<replaceable>X</replaceable></literal>,
+ e.g. <literal>modifySTRef</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3 id="sec-library-predicate-names">
+ <title>Predicate names</title>
+ <indexterm><primary>Predicate names</primary></indexterm>
+
+ <itemizedlist>
+ <listitem>
+ <para>Predicates, both non-monadic and monadic, testing a
+ property <replaceable>X</replaceable> have the name
+ <literal>is<replaceable>X</replaceable></literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3 id="sec-library-naming-conversions">
+ <title>Names for conversions</title>
+ <indexterm><primary>Names for conversions</primary></indexterm>
+
+ <itemizedlist>
+ <listitem>
+ <para>Functions converting a value of type
+ <replaceable>X</replaceable> to a value of type
+ <replaceable>Y</replaceable> have the name
+ <literal><replaceable>X</replaceable>To<replaceable>Y</replaceable></literal>
+ with all leading uppercase characters of
+ <replaceable>X</replaceable> converted to lower case,
+ e.g. <literal>stToIO</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Overloaded conversion functions of type
+ <literal>C a => a -> <replaceable>X</replaceable></literal>
+ have the name
+ <literal>to<replaceable>X</replaceable></literal>,
+ e.g. <literal>toInteger</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para> Overloaded conversion functions of type
+<literal>C a => <replaceable>X</replaceable> -> a</literal>
+ have the name <literal>from<replaceable>X</replaceable></literal>,
+e.g. <literal>fromInteger</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+
+ <sect3 id="sec-library-misc-names">
+ <title>Miscellaneous naming conventions</title>
+ <indexterm><primary>Miscellaneous naming
+ convetions</primary></indexterm>
+
+ <itemizedlist>
+ <listitem>
+ <para> An action that is identical to another one called
+ <replaceable>X</replaceable>, but discards the return
+ value has the name
+ <literal><replaceable>X</replaceable>_</literal>,
+ e.g. <literal>mapM</literal> and <literal>mapM_</literal>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>Functions and actions which are potentially
+ dangerous to use and leave some kind of proof obligation
+ to the programmer have the name
+ <literal>unsafe<replaceable>X</replaceable></literal>,
+ e.g. <literal>unsafePerformIO</literal>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>There are two conventions for binary and N-ary
+ variants of an associative operation: One convention uses
+ an operator or a short name for the binary operation and a
+ long name for the N-ary variant,
+ e.g. <literal>(+)</literal> and <literal>sum</literal>,
+ <literal>max</literal> and <literal>maximum</literal>. The
+ other convention suffixes the N-ary variant with
+ <literal>Many</literal>. (<emphasis>TODO</emphasis>: Add
+ Examples.)</para>
+ </listitem>
+
+ <listitem>
+ <para>If possible, names are chosen such that either plain
+ application or <literal>arg1 `operation` arg2</literal> is
+ correct English, e.g. <literal>isPrefixOf</literal> is
+ good for use in backquotes.</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+ </sect2>
+
+ <sect2 id="sec-library-misc-conventions">
+ <title>Library design conventions</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>Actions setting and modifying a kind of reference or
+ state return <literal>()</literal>, getting the value is
+ separate, e.g. <literal>writeIORef</literal> and
+ <literal>modifyIORef</literal> both return
+ <literal>()</literal>, only <literal>readIORef</literal>
+ returns the value in an <literal>IORef</literal>
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>A function or action taking a some kind of state and
+ returning a pair consisting of a result and a new state, the
+ result is the first element of the pair and the new state is
+ the second, see e.g. <literal>Random</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para>When the type <literal>Either</literal> is used to
+ encode an error condition and a normal result,
+ <literal>Left</literal> is used for the former and
+ <literal>Right</literal> for the latter, see
+ e.g. <literal>MonadEither</literal>.</para>
+ </listitem>
+
+ <listitem>
+ <para> A module corresponding to a class
+ (e.g. <literal>Bits</literal>) contains the class
+ definition, perhaps some auxiliary functions, and all
+ sensible instances for Prelude types, but nothing
+ more. Other modules containing types for which an instance
+ for the class in question makes sense contain the code for
+ the instance itself.</para>
+ </listitem>
+
+ <listitem>
+ <para> Record-like C bit fields or structs have a
+ record-like interface, i.e. pure getting and setting of
+ fields. (<emphasis>TODO</emphasis>: Clarify a little
+ bit. Add examples.)</para>
+ </listitem>
+
+ <listitem>
+ <para> Although the possibility of partial application
+ suggests the type
+
+<literal><replaceable>attr</replaceable> -> <replaceable>object</replaceable> -> <replaceable>object</replaceable></literal>
+
+ for functions setting an attribute or value, infix notation
+ with backquotes implies
+
+<literal><replaceable>object</replaceable> -> <replaceable>attr</replaceable> -> <replaceable>object</replaceable></literal>.
+
+ (<emphasis>TODO</emphasis>: Add Examples.)</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2 id="coding-style">
+ <title>Coding style conventions</title>
+ <para></para>
+ </sect2>
+
+ </sect1>
+
+ <sect1>
+ <title>Changes to standard Haskell 98 libraries</title>
+
+ <para>Some changes have been made to the standard Haskell 98
+ libraries in the new library scheme, both in the names of the
+ modules themselves and in their exported interfaces. Below is a
+ summary of those changes - at this time, the new libraries are
+ marked as provisional and are maintained by
+ <email>libraries@haskell.org</email>, so changes in the interfaces
+ are all up for discussion.</para>
+
+<screen>
+ modules with interface changes
+ ------------------------------
+
+ Array -> Data.Array
+ added instance Typeable (Array ix a)
+
+ Char -> Data.Char
+ no interface changes (should have instance Typeable?)
+
+ Complex -> Data.Complex
+ added instance Typeable (Complex a)
+
+ IO -> System.IO
+ added
+ hPutBuf :: Handle -> Ptr a -> Int -> IO ()
+ hGetBuf :: Handle -> Ptr a -> Int -> IO Int
+ fixIO :: (a -> IO a) -> IO a
+
+ List -> Data.List
+ exports [](..)
+
+ Numeric -> ????
+ not placed in hierarchy yet
+
+ System -> System.Exit, System.Environment, System.Cmd
+ split into three modules
+
+ just renamed, no interface changes:
+ -----------------------------------
+
+ CPUTTime -> System.CPUTime
+ Directory -> System.IO.Directory
+ Ix -> Data.Ix
+ Locale -> System.Locale
+ Monad -> Data.Monad
+ Random -> System.Radom
+ Ratio -> Data.Ratio
+ Time -> System.Time
+</screen>
+ </sect1>
+
+</article>
+
+
diff --git a/libraries/base/include/CTypes.h b/libraries/base/include/CTypes.h
new file mode 100644
index 0000000000..b2d5c3e40f
--- /dev/null
+++ b/libraries/base/include/CTypes.h
@@ -0,0 +1,335 @@
+/* -----------------------------------------------------------------------------
+ * $Id: CTypes.h,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * Dirty CPP hackery for CTypes/CTypesISO
+ *
+ * (c) The FFI task force, 2000
+ * -------------------------------------------------------------------------- */
+
+#include "MachDeps.h"
+
+/* As long as there is no automatic derivation of classes for newtypes we resort
+ to extremely dirty cpp-hackery. :-P Some care has to be taken when the
+ macros below are modified, otherwise the layout rule will bite you. */
+
+/* A hacked version for GHC follows the Haskell 98 version... */
+#ifndef __GLASGOW_HASKELL__
+
+#define NUMERIC_TYPE(T,C,S,B) \
+newtype T = T B deriving (Eq, Ord) ; \
+INSTANCE_NUM(T) ; \
+INSTANCE_READ(T) ; \
+INSTANCE_SHOW(T) ; \
+INSTANCE_ENUM(T) ; \
+INSTANCE_TYPEABLE(T,C,S) ;
+
+#define INTEGRAL_TYPE(T,C,S,B) \
+NUMERIC_TYPE(T,C,S,B) ; \
+INSTANCE_BOUNDED(T) ; \
+INSTANCE_REAL(T) ; \
+INSTANCE_INTEGRAL(T) ; \
+INSTANCE_BITS(T)
+
+#define FLOATING_TYPE(T,C,S,B) \
+NUMERIC_TYPE(T,C,S,B) ; \
+INSTANCE_REAL(T) ; \
+INSTANCE_FRACTIONAL(T) ; \
+INSTANCE_FLOATING(T) ; \
+INSTANCE_REALFRAC(T) ; \
+INSTANCE_REALFLOAT(T)
+
+#define INSTANCE_READ(T) \
+instance Read T where { \
+ readsPrec p s = fakeMap (\(x, t) -> (T x, t)) (readsPrec p s) }
+
+#define INSTANCE_SHOW(T) \
+instance Show T where { \
+ showsPrec p (T x) = showsPrec p x }
+
+#define INSTANCE_NUM(T) \
+instance Num T where { \
+ (T i) + (T j) = T (i + j) ; \
+ (T i) - (T j) = T (i - j) ; \
+ (T i) * (T j) = T (i * j) ; \
+ negate (T i) = T (negate i) ; \
+ abs (T i) = T (abs i) ; \
+ signum (T i) = T (signum i) ; \
+ fromInteger x = T (fromInteger x) }
+
+#define INSTANCE_TYPEABLE(T,C,S) \
+C :: TyCon ; \
+C = mkTyCon S ; \
+instance Typeable T where { \
+ typeOf _ = mkAppTy C [] }
+
+#define INSTANCE_BOUNDED(T) \
+instance Bounded T where { \
+ minBound = T minBound ; \
+ maxBound = T maxBound }
+
+#define INSTANCE_ENUM(T) \
+instance Enum T where { \
+ succ (T i) = T (succ i) ; \
+ pred (T i) = T (pred i) ; \
+ toEnum x = T (toEnum x) ; \
+ fromEnum (T i) = fromEnum i ; \
+ enumFrom (T i) = fakeMap T (enumFrom i) ; \
+ enumFromThen (T i) (T j) = fakeMap T (enumFromThen i j) ; \
+ enumFromTo (T i) (T j) = fakeMap T (enumFromTo i j) ; \
+ enumFromThenTo (T i) (T j) (T k) = fakeMap T (enumFromThenTo i j k) }
+
+#define INSTANCE_REAL(T) \
+instance Real T where { \
+ toRational (T i) = toRational i }
+
+#define INSTANCE_INTEGRAL(T) \
+instance Integral T where { \
+ (T i) `quot` (T j) = T (i `quot` j) ; \
+ (T i) `rem` (T j) = T (i `rem` j) ; \
+ (T i) `div` (T j) = T (i `div` j) ; \
+ (T i) `mod` (T j) = T (i `mod` j) ; \
+ (T i) `quotRem` (T j) = let (q,r) = i `quotRem` j in (T q, T r) ; \
+ (T i) `divMod` (T j) = let (d,m) = i `divMod` j in (T d, T m) ; \
+ toInteger (T i) = toInteger i }
+
+#define INSTANCE_BITS(T) \
+instance Bits T where { \
+ (T x) .&. (T y) = T (x .&. y) ; \
+ (T x) .|. (T y) = T (x .|. y) ; \
+ (T x) `xor` (T y) = T (x `xor` y) ; \
+ complement (T x) = T (complement x) ; \
+ shift (T x) n = T (shift x n) ; \
+ rotate (T x) n = T (rotate x n) ; \
+ bit n = T (bit n) ; \
+ setBit (T x) n = T (setBit x n) ; \
+ clearBit (T x) n = T (clearBit x n) ; \
+ complementBit (T x) n = T (complementBit x n) ; \
+ testBit (T x) n = testBit x n ; \
+ bitSize (T x) = bitSize x ; \
+ isSigned (T x) = isSigned x }
+
+#define INSTANCE_FRACTIONAL(T) \
+instance Fractional T where { \
+ (T x) / (T y) = T (x / y) ; \
+ recip (T x) = T (recip x) ; \
+ fromRational r = T (fromRational r) }
+
+#define INSTANCE_FLOATING(T) \
+instance Floating T where { \
+ pi = pi ; \
+ exp (T x) = T (exp x) ; \
+ log (T x) = T (log x) ; \
+ sqrt (T x) = T (sqrt x) ; \
+ (T x) ** (T y) = T (x ** y) ; \
+ (T x) `logBase` (T y) = T (x `logBase` y) ; \
+ sin (T x) = T (sin x) ; \
+ cos (T x) = T (cos x) ; \
+ tan (T x) = T (tan x) ; \
+ asin (T x) = T (asin x) ; \
+ acos (T x) = T (acos x) ; \
+ atan (T x) = T (atan x) ; \
+ sinh (T x) = T (sinh x) ; \
+ cosh (T x) = T (cosh x) ; \
+ tanh (T x) = T (tanh x) ; \
+ asinh (T x) = T (asinh x) ; \
+ acosh (T x) = T (acosh x) ; \
+ atanh (T x) = T (atanh x) }
+
+#define INSTANCE_REALFRAC(T) \
+instance RealFrac T where { \
+ properFraction (T x) = let (m,y) = properFraction x in (m, T y) ; \
+ truncate (T x) = truncate x ; \
+ round (T x) = round x ; \
+ ceiling (T x) = ceiling x ; \
+ floor (T x) = floor x }
+
+#define INSTANCE_REALFLOAT(T) \
+instance RealFloat T where { \
+ floatRadix (T x) = floatRadix x ; \
+ floatDigits (T x) = floatDigits x ; \
+ floatRange (T x) = floatRange x ; \
+ decodeFloat (T x) = decodeFloat x ; \
+ encodeFloat m n = T (encodeFloat m n) ; \
+ exponent (T x) = exponent x ; \
+ significand (T x) = T (significand x) ; \
+ scaleFloat n (T x) = T (scaleFloat n x) ; \
+ isNaN (T x) = isNaN x ; \
+ isInfinite (T x) = isInfinite x ; \
+ isDenormalized (T x) = isDenormalized x ; \
+ isNegativeZero (T x) = isNegativeZero x ; \
+ isIEEE (T x) = isIEEE x ; \
+ (T x) `atan2` (T y) = T (x `atan2` y) }
+
+#else /* __GLASGOW_HASKELL__ */
+
+/* On GHC, we just cast the type of each method to the underlying
+ * type. This means that GHC only needs to generate the dictionary
+ * for each instance, rather than a new function for each method (the
+ * simplifier currently isn't clever enough to reduce a method that
+ * simply deconstructs a newtype and calls the underlying method into
+ * an indirection to the underlying method, so that's what we're doing
+ * here).
+ */
+
+#define NUMERIC_TYPE(T,C,S,B) \
+newtype T = T B ; \
+INSTANCE_EQ(T,B) ; \
+INSTANCE_ORD(T,B) ; \
+INSTANCE_NUM(T,B) ; \
+INSTANCE_READ(T,B) ; \
+INSTANCE_SHOW(T,B) ; \
+INSTANCE_ENUM(T,B)
+
+#define INTEGRAL_TYPE(T,C,S,B) \
+NUMERIC_TYPE(T,C,S,B) ; \
+INSTANCE_BOUNDED(T,B) ; \
+INSTANCE_REAL(T,B) ; \
+INSTANCE_INTEGRAL(T,B) ; \
+INSTANCE_BITS(T,B)
+
+#define FLOATING_TYPE(T,C,S,B) \
+NUMERIC_TYPE(T,C,S,B) ; \
+INSTANCE_REAL(T,B) ; \
+INSTANCE_FRACTIONAL(T,B) ; \
+INSTANCE_FLOATING(T,B) ; \
+INSTANCE_REALFRAC(T) ; \
+INSTANCE_REALFLOAT(T,B)
+
+#define INSTANCE_EQ(T,B) \
+instance Eq T where { \
+ (==) = unsafeCoerce# ((==) :: B -> B -> Bool); \
+ (/=) = unsafeCoerce# ((/=) :: B -> B -> Bool); }
+
+#define INSTANCE_ORD(T,B) \
+instance Ord T where { \
+ compare = unsafeCoerce# (compare :: B -> B -> Ordering); \
+ (<) = unsafeCoerce# ((<) :: B -> B -> Bool); \
+ (<=) = unsafeCoerce# ((<=) :: B -> B -> Bool); \
+ (>=) = unsafeCoerce# ((>=) :: B -> B -> Bool); \
+ (>) = unsafeCoerce# ((>) :: B -> B -> Bool); \
+ max = unsafeCoerce# (max :: B -> B -> B); \
+ min = unsafeCoerce# (min :: B -> B -> B); }
+
+#define INSTANCE_READ(T,B) \
+instance Read T where { \
+ readsPrec = unsafeCoerce# (readsPrec :: Int -> ReadS B); \
+ readList = unsafeCoerce# (readList :: ReadS [B]); }
+
+#define INSTANCE_SHOW(T,B) \
+instance Show T where { \
+ showsPrec = unsafeCoerce# (showsPrec :: Int -> B -> ShowS); \
+ show = unsafeCoerce# (show :: B -> String); \
+ showList = unsafeCoerce# (showList :: [B] -> ShowS); }
+
+#define INSTANCE_NUM(T,B) \
+instance Num T where { \
+ (+) = unsafeCoerce# ((+) :: B -> B -> B); \
+ (-) = unsafeCoerce# ((-) :: B -> B -> B); \
+ (*) = unsafeCoerce# ((*) :: B -> B -> B); \
+ negate = unsafeCoerce# (negate :: B -> B); \
+ abs = unsafeCoerce# (abs :: B -> B); \
+ signum = unsafeCoerce# (signum :: B -> B); \
+ fromInteger = unsafeCoerce# (fromInteger :: Integer -> B); }
+
+#define INSTANCE_BOUNDED(T,B) \
+instance Bounded T where { \
+ minBound = T minBound ; \
+ maxBound = T maxBound }
+
+#define INSTANCE_ENUM(T,B) \
+instance Enum T where { \
+ succ = unsafeCoerce# (succ :: B -> B); \
+ pred = unsafeCoerce# (pred :: B -> B); \
+ toEnum = unsafeCoerce# (toEnum :: Int -> B); \
+ fromEnum = unsafeCoerce# (fromEnum :: B -> Int); \
+ enumFrom = unsafeCoerce# (enumFrom :: B -> [B]); \
+ enumFromThen = unsafeCoerce# (enumFromThen :: B -> B -> [B]); \
+ enumFromTo = unsafeCoerce# (enumFromTo :: B -> B -> [B]); \
+ enumFromThenTo = unsafeCoerce# (enumFromThenTo :: B -> B -> B -> [B]);}
+
+#define INSTANCE_REAL(T,B) \
+instance Real T where { \
+ toRational = unsafeCoerce# (toRational :: B -> Rational) }
+
+#define INSTANCE_INTEGRAL(T,B) \
+instance Integral T where { \
+ quot = unsafeCoerce# (quot:: B -> B -> B); \
+ rem = unsafeCoerce# (rem:: B -> B -> B); \
+ div = unsafeCoerce# (div:: B -> B -> B); \
+ mod = unsafeCoerce# (mod:: B -> B -> B); \
+ quotRem = unsafeCoerce# (quotRem:: B -> B -> (B,B)); \
+ divMod = unsafeCoerce# (divMod:: B -> B -> (B,B)); \
+ toInteger = unsafeCoerce# (toInteger:: B -> Integer); }
+
+#define INSTANCE_BITS(T,B) \
+instance Bits T where { \
+ (.&.) = unsafeCoerce# ((.&.) :: B -> B -> B); \
+ (.|.) = unsafeCoerce# ((.|.) :: B -> B -> B); \
+ xor = unsafeCoerce# (xor:: B -> B -> B); \
+ complement = unsafeCoerce# (complement:: B -> B); \
+ shift = unsafeCoerce# (shift:: B -> Int -> B); \
+ rotate = unsafeCoerce# (rotate:: B -> Int -> B); \
+ bit = unsafeCoerce# (bit:: Int -> B); \
+ setBit = unsafeCoerce# (setBit:: B -> Int -> B); \
+ clearBit = unsafeCoerce# (clearBit:: B -> Int -> B); \
+ complementBit = unsafeCoerce# (complementBit:: B -> Int -> B); \
+ testBit = unsafeCoerce# (testBit:: B -> Int -> Bool); \
+ bitSize = unsafeCoerce# (bitSize:: B -> Int); \
+ isSigned = unsafeCoerce# (isSigned:: B -> Bool); }
+
+#define INSTANCE_FRACTIONAL(T,B) \
+instance Fractional T where { \
+ (/) = unsafeCoerce# ((/) :: B -> B -> B); \
+ recip = unsafeCoerce# (recip :: B -> B); \
+ fromRational = unsafeCoerce# (fromRational :: Rational -> B); }
+
+#define INSTANCE_FLOATING(T,B) \
+instance Floating T where { \
+ pi = unsafeCoerce# (pi :: B); \
+ exp = unsafeCoerce# (exp :: B -> B); \
+ log = unsafeCoerce# (log :: B -> B); \
+ sqrt = unsafeCoerce# (sqrt :: B -> B); \
+ (**) = unsafeCoerce# ((**) :: B -> B -> B); \
+ logBase = unsafeCoerce# (logBase :: B -> B -> B); \
+ sin = unsafeCoerce# (sin :: B -> B); \
+ cos = unsafeCoerce# (cos :: B -> B); \
+ tan = unsafeCoerce# (tan :: B -> B); \
+ asin = unsafeCoerce# (asin :: B -> B); \
+ acos = unsafeCoerce# (acos :: B -> B); \
+ atan = unsafeCoerce# (atan :: B -> B); \
+ sinh = unsafeCoerce# (sinh :: B -> B); \
+ cosh = unsafeCoerce# (cosh :: B -> B); \
+ tanh = unsafeCoerce# (tanh :: B -> B); \
+ asinh = unsafeCoerce# (asinh :: B -> B); \
+ acosh = unsafeCoerce# (acosh :: B -> B); \
+ atanh = unsafeCoerce# (atanh :: B -> B); }
+
+/* The coerce trick doesn't work for RealFrac, these methods are
+ * polymorphic and overloaded.
+ */
+#define INSTANCE_REALFRAC(T) \
+instance RealFrac T where { \
+ properFraction (T x) = let (m,y) = properFraction x in (m, T y) ; \
+ truncate (T x) = truncate x ; \
+ round (T x) = round x ; \
+ ceiling (T x) = ceiling x ; \
+ floor (T x) = floor x }
+
+#define INSTANCE_REALFLOAT(T,B) \
+instance RealFloat T where { \
+ floatRadix = unsafeCoerce# (floatRadix :: B -> Integer); \
+ floatDigits = unsafeCoerce# (floatDigits :: B -> Int); \
+ floatRange = unsafeCoerce# (floatRange :: B -> (Int,Int)); \
+ decodeFloat = unsafeCoerce# (decodeFloat :: B -> (Integer,Int)); \
+ encodeFloat = unsafeCoerce# (encodeFloat :: Integer -> Int -> B); \
+ exponent = unsafeCoerce# (exponent :: B -> Int); \
+ significand = unsafeCoerce# (significand :: B -> B); \
+ scaleFloat = unsafeCoerce# (scaleFloat :: Int -> B -> B); \
+ isNaN = unsafeCoerce# (isNaN :: B -> Bool); \
+ isInfinite = unsafeCoerce# (isInfinite :: B -> Bool); \
+ isDenormalized = unsafeCoerce# (isDenormalized :: B -> Bool); \
+ isNegativeZero = unsafeCoerce# (isNegativeZero :: B -> Bool); \
+ isIEEE = unsafeCoerce# (isIEEE :: B -> Bool); \
+ atan2 = unsafeCoerce# (atan2 :: B -> B -> B); }
+
+#endif /* __GLASGOW_HASKELL__ */
diff --git a/libraries/base/include/Dynamic.h b/libraries/base/include/Dynamic.h
new file mode 100644
index 0000000000..eed01bca6d
--- /dev/null
+++ b/libraries/base/include/Dynamic.h
@@ -0,0 +1,27 @@
+/* -----------------------------------------------------------------------------
+ * $Id: Dynamic.h,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * Macros to help make Typeable instances.
+ * -------------------------------------------------------------------------- */
+
+#define INSTANCE_TYPEABLE0(tycon,tcname,str) \
+tcname = mkTyCon str; \
+instance Typeable tycon where { typeOf _ = mkAppTy tcname [] }
+
+#define INSTANCE_TYPEABLE1(tycon,tcname,str) \
+tcname = mkTyCon str; \
+instance Typeable a => Typeable (tycon a) where { \
+ typeOf x = mkAppTy tcname [typeOf ((undefined :: tycon a -> a) x) ] }
+
+#define INSTANCE_TYPEABLE2(tycon,tcname,str) \
+tcname = mkTyCon str; \
+instance (Typeable a, Typeable b) => Typeable (tycon a b) where { \
+ typeOf x = mkAppTy tcname [typeOf ((undefined :: tycon a b -> a) x), \
+ typeOf ((undefined :: tycon a b -> b) x)] }
+
+#define INSTANCE_TYPEABLE3(tycon,tcname,str) \
+tcname = mkTyCon str; \
+instance (Typeable a, Typeable b, Typeable c) => Typeable (tycon a b c) where {\
+ typeOf a = mkAppTy tcname [typeOf ((undefined :: tycon a b c -> a) a), \
+ typeOf ((undefined :: tycon a b c -> b) a), \
+ typeOf ((undefined :: tycon a b c -> c) a)] }
diff --git a/libraries/base/include/HsCore.h b/libraries/base/include/HsCore.h
new file mode 100644
index 0000000000..1bce35114c
--- /dev/null
+++ b/libraries/base/include/HsCore.h
@@ -0,0 +1,94 @@
+/* -----------------------------------------------------------------------------
+ * $Id: HsCore.h,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * Definitions for package `core' which are visible in Haskell land.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#ifndef HSCORE_H
+#define HSCORE_H
+
+#include "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if defined(HAVE_GETTIMEOFDAY)
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
+#elif defined(HAVE_GETCLOCK)
+# ifdef HAVE_SYS_TIMERS_H
+# define POSIX_4D9 1
+# include <sys/timers.h>
+# endif
+#endif
+#if defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+#ifdef HAVE_SYS_TIMEB_H
+#include <sys/timeb.h>
+#endif
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
+
+#if !defined(mingw32_TARGET_OS) && !defined(irix_TARGET_OS)
+# if defined(HAVE_SYS_RESOURCE_H)
+# include <sys/resource.h>
+# endif
+#endif
+
+#ifdef hpux_TARGET_OS
+#include <sys/syscall.h>
+#define getrusage(a, b) syscall(SYS_GETRUSAGE, a, b)
+#define HAVE_GETRUSAGE
+#endif
+
+/* For System */
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+
+#include "lockFile.h"
+
+#include "HsFFI.h"
+
+/* in ghc_errno.c */
+int *ghcErrno(void);
+
+/* in system.c */
+HsInt systemCmd(HsAddr cmd);
+
+/* in inputReady.c */
+int inputReady(int fd, int msecs);
+
+/* in progargs.c */
+HsAddr get_prog_argv(void);
+HsInt get_prog_argc();
+
+#endif
diff --git a/libraries/base/include/PackedString.h b/libraries/base/include/PackedString.h
new file mode 100644
index 0000000000..a0fc8309c3
--- /dev/null
+++ b/libraries/base/include/PackedString.h
@@ -0,0 +1,14 @@
+/* -----------------------------------------------------------------------------
+ * $Id: PackedString.h,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * C Definitions for PackedString.hs
+ *
+ * ---------------------------------------------------------------------------*/
+
+#ifndef PACKEDSTRING_H
+#define PACKEDSTRING_H
+
+/* PackedString.c */
+extern StgInt byteArrayHasNUL__ (StgByteArray ba, StgInt len);
+
+#endif
diff --git a/libraries/base/include/ghc_errno.h b/libraries/base/include/ghc_errno.h
new file mode 100644
index 0000000000..33b5dce54c
--- /dev/null
+++ b/libraries/base/include/ghc_errno.h
@@ -0,0 +1,15 @@
+/* -----------------------------------------------------------------------------
+ * $Id: ghc_errno.h,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * (c) The GHC Team 2001
+ *
+ * Haskell-usable version of errno
+ *
+ * ---------------------------------------------------------------------------*/
+
+#ifndef GHCERRNO_H
+#define GHCERRNO_H
+
+int *ghcErrno(void);
+
+#endif
diff --git a/libraries/base/include/lockFile.h b/libraries/base/include/lockFile.h
new file mode 100644
index 0000000000..508640f801
--- /dev/null
+++ b/libraries/base/include/lockFile.h
@@ -0,0 +1,10 @@
+/*
+ * (c) The University of Glasgow 2001
+ *
+ * $Id: lockFile.h,v 1.1 2001/06/28 14:15:04 simonmar Exp $
+ *
+ * lockFile header
+ */
+
+int lockFile(int fd, int for_writing, int exclusive);
+int unlockFile(int fd);