summaryrefslogtreecommitdiff
path: root/ghc/lib/hbc/Native.hs
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/lib/hbc/Native.hs')
-rw-r--r--ghc/lib/hbc/Native.hs356
1 files changed, 356 insertions, 0 deletions
diff --git a/ghc/lib/hbc/Native.hs b/ghc/lib/hbc/Native.hs
new file mode 100644
index 0000000000..a0d4d99663
--- /dev/null
+++ b/ghc/lib/hbc/Native.hs
@@ -0,0 +1,356 @@
+#if defined(__YALE_HASKELL__)
+-- Native.hs -- native data conversions and I/O
+--
+-- author : Sandra Loosemore
+-- date : 07 Jun 1994
+--
+--
+-- Unlike in the original hbc version of this library, a Byte is a completely
+-- abstract data type and not a character. You can't read and write Bytes
+-- to ordinary text files; you must use the operations defined here on
+-- Native files.
+-- It's guaranteed to be more efficient to read and write objects directly
+-- to a file than to do the conversion to a Byte stream and read/write
+-- the Byte stream.
+#endif
+
+module Native(
+ Native(..), Bytes(..),
+ shortIntToBytes, bytesToShortInt,
+ longIntToBytes, bytesToLongInt,
+ showB, readB
+#if __HASKELL1__ < 3
+ , Maybe..
+#endif
+#if defined(__YALE_HASKELL__)
+ , openInputByteFile, openOutputByteFile, closeByteFile
+ , readBFile, readBytesFromByteFile
+ , shortIntToByteFile, bytesToShortIntIO
+ , ByteFile
+ , Byte
+#endif
+ ) where
+
+#if __HASKELL1__ < 3
+import {-flummox mkdependHS-}
+ Maybe
+#endif
+
+#if defined(__YALE_HASKELL__)
+import NativePrims
+
+-- these data types are completely opaque on the Haskell side.
+
+data Byte = Byte
+data ByteFile = ByteFile
+type Bytes = [Byte]
+
+instance Text(Byte) where
+ showsPrec _ _ = showString "Byte"
+
+instance Text(ByteFile) where
+ showsPrec _ _ = showString "ByteFile"
+
+-- Byte file primitives
+
+openInputByteFile :: String -> IO (ByteFile)
+openOutputByteFile :: String -> IO (ByteFile)
+closeByteFile :: ByteFile -> IO ()
+
+openInputByteFile = primOpenInputByteFile
+openOutputByteFile = primOpenOutputByteFile
+closeByteFile = primCloseByteFile
+#endif {- YALE-}
+
+#if defined(__GLASGOW_HASKELL__)
+import ByteOps -- partain
+type Bytes = [Char]
+#endif
+
+#if defined(__HBC__)
+import LMLbyteops
+type Bytes = [Char]
+#endif
+
+-- Here are the basic operations defined on the class.
+
+class Native a where
+
+ -- these are primitives
+ showBytes :: a -> Bytes -> Bytes -- convert to bytes
+ readBytes :: Bytes -> Maybe (a, Bytes) -- get an item and the rest
+#if defined(__YALE_HASKELL__)
+ showByteFile :: a -> ByteFile -> IO ()
+ readByteFile :: ByteFile -> IO a
+#endif
+
+ -- these are derived
+ listShowBytes :: [a] -> Bytes -> Bytes -- convert a list to bytes
+ listReadBytes :: Int -> Bytes -> Maybe ([a], Bytes) -- get n items and the rest
+#if defined(__YALE_HASKELL__)
+ listShowByteFile :: [a] -> ByteFile -> IO ()
+ listReadByteFile :: Int -> ByteFile -> IO [a]
+#endif
+
+ -- here are defaults for the derived methods.
+
+ listShowBytes [] bs = bs
+ listShowBytes (x:xs) bs = showBytes x (listShowBytes xs bs)
+
+ listReadBytes 0 bs = Just ([], bs)
+ listReadBytes n bs =
+ case readBytes bs of
+ Nothing -> Nothing
+ Just (x,bs') ->
+ case listReadBytes (n-1) bs' of
+ Nothing -> Nothing
+ Just (xs,bs'') -> Just (x:xs, bs'')
+
+#if defined(__YALE_HASKELL__)
+ listShowByteFile l f =
+ foldr (\ head tail -> (showByteFile head f) >> tail)
+ (return ())
+ l
+
+ listReadByteFile 0 f =
+ return []
+ listReadByteFile n f =
+ readByteFile f >>= \ h ->
+ listReadByteFile (n - 1) f >>= \ t ->
+ return (h:t)
+#endif
+
+#if ! defined(__YALE_HASKELL__)
+-- Some utilities that Yale doesn't use
+hasNElems :: Int -> [a] -> Bool
+hasNElems 0 _ = True
+hasNElems 1 (_:_) = True -- speedup
+hasNElems 2 (_:_:_) = True -- speedup
+hasNElems 3 (_:_:_:_) = True -- speedup
+hasNElems 4 (_:_:_:_:_) = True -- speedup
+hasNElems _ [] = False
+hasNElems n (_:xs) = hasNElems (n-1) xs
+
+lenLong = length (longToBytes 0 [])
+lenInt = length (intToBytes 0 [])
+lenShort = length (shortToBytes 0 [])
+lenFloat = length (floatToBytes 0 [])
+lenDouble = length (doubleToBytes 0 [])
+#endif
+
+-- Basic instances, defined as primitives
+
+instance Native Char where
+#if defined(__YALE_HASKELL__)
+ showBytes = primCharShowBytes
+ readBytes = primCharReadBytes
+ showByteFile = primCharShowByteFile
+ readByteFile = primCharReadByteFile
+#else
+ showBytes c bs = c:bs
+ readBytes [] = Nothing
+ readBytes (c:cs) = Just (c,cs)
+ listReadBytes n bs = f n bs []
+ where f 0 bs cs = Just (reverse cs, bs)
+ f _ [] _ = Nothing
+ f n (b:bs) cs = f (n-1::Int) bs (b:cs)
+#endif
+
+instance Native Int where
+#if defined(__YALE_HASKELL__)
+ showBytes = primIntShowBytes
+ readBytes = primIntReadBytes
+ showByteFile = primIntShowByteFile
+ readByteFile = primIntReadByteFile
+#else
+ showBytes i bs = intToBytes i bs
+ readBytes bs = if hasNElems lenInt bs then Just (bytesToInt bs) else Nothing
+#endif
+
+instance Native Float where
+#if defined(__YALE_HASKELL__)
+ showBytes = primFloatShowBytes
+ readBytes = primFloatReadBytes
+ showByteFile = primFloatShowByteFile
+ readByteFile = primFloatReadByteFile
+#else
+ showBytes i bs = floatToBytes i bs
+ readBytes bs = if hasNElems lenFloat bs then Just (bytesToFloat bs) else Nothing
+#endif
+
+instance Native Double where
+#if defined(__YALE_HASKELL__)
+ showBytes = primDoubleShowBytes
+ readBytes = primDoubleReadBytes
+ showByteFile = primDoubleShowByteFile
+ readByteFile = primDoubleReadByteFile
+#else
+ showBytes i bs = doubleToBytes i bs
+ readBytes bs = if hasNElems lenDouble bs then Just (bytesToDouble bs) else Nothing
+#endif
+
+instance Native Bool where
+#if defined(__YALE_HASKELL__)
+ showBytes = primBoolShowBytes
+ readBytes = primBoolReadBytes
+ showByteFile = primBoolShowByteFile
+ readByteFile = primBoolReadByteFile
+#else
+ showBytes b bs = if b then '\x01':bs else '\x00':bs
+ readBytes [] = Nothing
+ readBytes (c:cs) = Just(c/='\x00', cs)
+#endif
+
+#if defined(__YALE_HASKELL__)
+-- Byte instances, so you can write Bytes to a ByteFile
+
+instance Native Byte where
+ showBytes = (:)
+ readBytes l =
+ case l of
+ [] -> Nothing
+ h:t -> Just(h,t)
+ showByteFile = primByteShowByteFile
+ readByteFile = primByteReadByteFile
+#endif
+
+-- A pair is stored as two consecutive items.
+instance (Native a, Native b) => Native (a,b) where
+ showBytes (a,b) = showBytes a . showBytes b
+ readBytes bs = readBytes bs `thenMaybe` \(a,bs') ->
+ readBytes bs' `thenMaybe` \(b,bs'') ->
+ Just ((a,b), bs'')
+#if defined(__YALE_HASKELL__)
+ showByteFile (a,b) f = (showByteFile a f) >> (showByteFile b f)
+
+ readByteFile f =
+ readByteFile f >>= \ a ->
+ readByteFile f >>= \ b ->
+ return (a,b)
+#endif
+
+-- A triple is stored as three consectutive items.
+instance (Native a, Native b, Native c) => Native (a,b,c) where
+ showBytes (a,b,c) = showBytes a . showBytes b . showBytes c
+ readBytes bs = readBytes bs `thenMaybe` \(a,bs') ->
+ readBytes bs' `thenMaybe` \(b,bs'') ->
+ readBytes bs'' `thenMaybe` \(c,bs''') ->
+ Just ((a,b,c), bs''')
+#if defined(__YALE_HASKELL__)
+ showByteFile (a,b,c) f =
+ (showByteFile a f) >>
+ (showByteFile b f) >>
+ (showByteFile c f)
+
+ readByteFile f =
+ readByteFile f >>= \ a ->
+ readByteFile f >>= \ b ->
+ readByteFile f >>= \ c ->
+ return (a,b,c)
+#endif
+
+-- A list is stored with an Int with the number of items followed by the items.
+instance (Native a) => Native [a] where
+ showBytes xs bs = showBytes (length xs) (f xs) where f [] = bs
+ f (x:xs) = showBytes x (f xs)
+ readBytes bs = readBytes bs `thenMaybe` \(n,bs') ->
+ listReadBytes n bs' `thenMaybe` \(xs, bs'') ->
+ Just (xs, bs'')
+#if defined(__YALE_HASKELL__)
+ showByteFile l f = (showByteFile (length l) f) >> (listShowByteFile l f)
+ readByteFile f = readByteFile f >>= \ n -> listReadByteFile n f
+#endif
+
+-- A Maybe is stored as a Boolean possibly followed by a value
+instance (Native a) => Native (Maybe a) where
+#if !defined(__YALE_HASKELL__)
+ showBytes Nothing = ('\x00' :)
+ showBytes (Just x) = ('\x01' :) . showBytes x
+ readBytes ('\x00':bs) = Just (Nothing, bs)
+ readBytes ('\x01':bs) = readBytes bs `thenMaybe` \(a,bs') ->
+ Just (Just a, bs')
+ readBytes _ = Nothing
+#else
+ showBytes (Just a) = showBytes True . showBytes a
+ showBytes Nothing = showBytes False
+ readBytes bs =
+ readBytes bs `thenMaybe` \ (isJust, bs') ->
+ if isJust then
+ readBytes bs' `thenMaybe` \ (a, bs'') ->
+ Just (Just a, bs'')
+ else
+ Just (Nothing, bs')
+
+ showByteFile (Just a) f = showByteFile True f >> showByteFile a f
+ showByteFile Nothing f = showByteFile False f
+ readByteFile f =
+ readByteFile f >>= \ isJust ->
+ if isJust then
+ readByteFile f >>= \ a ->
+ return (Just a)
+ else
+ return Nothing
+#endif
+
+instance (Native a, Ix a, Native b) => Native (Array a b) where
+ showBytes a = showBytes (bounds a) . showBytes (elems a)
+ readBytes bs = readBytes bs `thenMaybe` \(b, bs')->
+ readBytes bs' `thenMaybe` \(xs, bs'')->
+ Just (listArray b xs, bs'')
+
+shortIntToBytes :: Int -> Bytes -> Bytes
+bytesToShortInt :: Bytes -> Maybe (Int, Bytes)
+longIntToBytes :: Int -> Bytes -> Bytes
+bytesToLongInt :: Bytes -> Maybe (Int, Bytes)
+#if defined(__YALE_HASKELL__)
+shortIntToByteFile :: Int -> ByteFile -> IO ()
+bytesToShortIntIO :: ByteFile -> IO Int
+#endif
+
+#if defined(__YALE_HASKELL__)
+-- These functions are like the primIntxx but use a "short" rather than
+-- "int" representation.
+shortIntToBytes = primShortShowBytes
+bytesToShortInt = primShortReadBytes
+shortIntToByteFile = primShortShowByteFile
+bytesToShortIntIO = primShortReadByteFile
+
+#else {-! YALE-}
+
+shortIntToBytes s bs = shortToBytes s bs
+
+bytesToShortInt bs = if hasNElems lenShort bs then Just (bytesToShort bs) else Nothing
+
+longIntToBytes s bs = longToBytes s bs
+
+bytesToLongInt bs = if hasNElems lenLong bs then Just (bytesToLong bs) else Nothing
+
+#endif {-! YALE-}
+
+showB :: (Native a) => a -> Bytes
+showB x = showBytes x []
+
+readB :: (Native a) => Bytes -> a
+readB bs =
+ case readBytes bs of
+ Just (x,[]) -> x
+ Just (_,_) -> error "Native.readB data too long"
+ Nothing -> error "Native.readB data too short"
+
+#if defined(__YALE_HASKELL__)
+readBFile :: String -> IO(Bytes)
+readBFile name =
+ openInputByteFile name >>= \ f ->
+ readBytesFromByteFile f
+
+readBytesFromByteFile :: ByteFile -> IO(Bytes)
+readBytesFromByteFile f =
+ try
+ (primByteReadByteFile f >>= \ h ->
+ readBytesFromByteFile f >>= \ t ->
+ return (h:t))
+ onEOF
+ where
+ onEOF EOF = closeByteFile f >> return []
+ onEOF err = closeByteFile f >> failwith err
+#endif