on master help sign in
Simplify the internal array code

There was no value (but also no performance penalty) to it being based around a typeclass, so I ripped that out, along with Hugs support that I'd never really compile-tested. --HG-- extra : convert_revision : 9a9ad4f2255aeab044b210860b950e8454326cfe

commiteac91479c9a983b807d852bed9110df95435220c authorBryan O'Sullivan <bos@serpentine.com> dateSun 15 Aug 2010, 00:40 (16 years ago) parent09e803d
6 files changed+72−195
Data/Text.hs+1−2 Data/Text/Array.hs+56−175 Data/Text/IO/Internal.hs+2−2 Data/Text/Internal.hs+3−4 Data/Text/Lazy/Builder.hs+9−11 Data/Text/UnsafeChar.hs+1−1
Data/Text.hs+1−2
@@ -187,7 +187,6 @@ import Control.Monad.ST (ST)
187187import qualified Data.Text.Array as A
188188import qualified Data.List as L
189189import Data.Monoid (Monoid(..))
190−import Data.Word (Word16)
191190import Data.String (IsString(..))
192191import qualified Data.Text.Fusion as S
193192import qualified Data.Text.Fusion.Common as S
@@ -308,7 +307,7 @@ append (Text arr1 off1 len1) (Text arr2 off2 len2) = Text (A.run x) 0 len
308307 unstream (S.append (stream t1) (stream t2)) = append t1 t2
309308 #-}
310309
311−copy :: forall s. A.MArray s Word16 -> Int -> A.Array Word16 -> Int -> Int
310+copy :: forall s. A.MArray s -> Int -> A.Array -> Int -> Int
312311 -> ST s ()
313312copy dest i0 src j0 top = go i0 j0
314313 where
Data/Text/Array.hs+56−175
@@ -1,5 +1,4 @@
1−{-# LANGUAGE BangPatterns, CPP, ExistentialQuantification, MagicHash,
2− Rank2Types, ScopedTypeVariables, UnboxedTuples #-}
1+{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples #-}
32{-# OPTIONS_GHC -fno-warn-unused-matches #-}
43-- |
54-- Module : Data.Text.Array
@@ -27,20 +26,20 @@ module Data.Text.Array
2726 (
2827 -- * Types
2928 IArray(..)
30− , Elt(..)
3129 , Array
3230 , MArray
3331
3432 -- * Functions
33+ , copy
3534 , empty
36− , new
37− , unsafeNew
38− , unsafeFreeze
3935 , run
4036 , run2
4137 , toList
42− , copy
4338 , unsafeCopy
39+ , unsafeFreeze
40+ , unsafeIndex
41+ , unsafeNew
42+ , unsafeWrite
4443 ) where
4544
4645#if 0
@@ -53,125 +52,48 @@ if (_k_) < 0 || (_k_) >= (_len_) then error ("Data.Text.Array." ++ (_func_) ++ "
5352#define CHECK_BOUNDS(_func_,_len_,_k_)
5453#endif
5554
56−#if defined(__GLASGOW_HASKELL__)
5755#include "MachDeps.h"
5856
57+import Control.Exception (assert)
58+import Data.Text.UnsafeShift (shiftL)
5959import GHC.Base (ByteArray#, MutableByteArray#, Int(..),
6060 indexWord16Array#, newByteArray#,
6161 readWord16Array#, unsafeCoerce#,
62− writeWord16Array#, (*#))
63−import GHC.Prim (Int#)
62+ writeWord16Array#)
6463import GHC.ST (ST(..), runST)
6564import GHC.Word (Word16(..))
66−
67−#elif defined(__HUGS__)
68−
69−import Hugs.ByteArray (ByteArray, MutableByteArray, readByteArray,
70− newMutableByteArray, readMutableByteArray,
71− unsafeFreezeMutableByteArray, writeMutableByteArray)
72−import Foreign.Storable (Storable, sizeOf)
73−import Hugs.ST (ST(..), runST)
74−
75−#else
76−# error not implemented for this compiler
77−#endif
78−
79−import Control.Exception (assert)
80−import Data.Typeable (Typeable1(..), Typeable2(..), TyCon, mkTyCon, mkTyConApp)
8165import Prelude hiding (length, read)
8266
83−#include "Typeable.h"
84−
8567-- | Immutable array type.
86−data Array e = Array
87− {-# UNPACK #-} !Int -- length (in units of e, not bytes)
88−#if defined(__GLASGOW_HASKELL__)
68+data Array = Array
69+ {-# UNPACK #-} !Int -- length (in units of Word16, not bytes)
8970 ByteArray#
90−#elif defined(__HUGS__)
91− !ByteArray
92−#endif
93−
94−INSTANCE_TYPEABLE1(Array,arrayTc,"Array")
9571
9672-- | Mutable array type, for use in the ST monad.
97−data MArray s e = MArray
98− {-# UNPACK #-} !Int -- length (in units of e, not bytes)
99−#if defined(__GLASGOW_HASKELL__)
73+data MArray s = MArray
74+ {-# UNPACK #-} !Int -- length (in units of Word16, not bytes)
10075 (MutableByteArray# s)
101−#elif defined(__HUGS__)
102− !(MutableByteArray s)
103−#endif
104−
105−INSTANCE_TYPEABLE2(MArray,mArrayTc,"MArray")
10676
10777-- | Operations supported by all arrays.
10878class IArray a where
10979 -- | Return the length of an array.
11080 length :: a -> Int
11181
112−instance IArray (Array e) where
82+instance IArray Array where
11383 length (Array len _ba) = len
11484 {-# INLINE length #-}
11585
116−instance (Elt e, Show e) => Show (Array e) where
117− show = show . toList
118−
119−instance IArray (MArray s e) where
86+instance IArray (MArray s) where
12087 length (MArray len _ba) = len
12188 {-# INLINE length #-}
12289
123−check :: IArray a => String -> a -> Int -> (a -> Int -> b) -> b
124−check func ary i f
125− | i >= 0 && i < length ary = f ary i
126− | otherwise = error ("Data.Array.Flat." ++ func ++ ": index out of bounds")
127−{-# INLINE check #-}
128−
129−-- | Operations supported by all elements that can be stored in
130−-- arrays.
131−class Elt e where
132− -- | Indicate how many bytes would be used for an array of the
133− -- given size.
134− bytesInArray :: Int -> e -> Int
135− -- | Unchecked read of an immutable array. May return garbage or
136− -- crash on an out-of-bounds access.
137− unsafeIndex :: Array e -> Int -> e
138− -- | Unchecked read of a mutable array. May return garbage or
139− -- crash on an out-of-bounds access.
140− unsafeRead :: MArray s e -> Int -> ST s e
141− -- | Unchecked write of a mutable array. May return garbage or
142− -- crash on an out-of-bounds access.
143− unsafeWrite :: MArray s e -> Int -> e -> ST s ()
144−
145− -- | Read an immutable array. An invalid index results in a
146− -- runtime error.
147− index :: Array e -> Int -> e
148− index ary i = check "index" ary i unsafeIndex
149− {-# INLINE index #-}
150−
151− -- | Read a mutable array. An invalid index results in a runtime
152− -- error.
153− read :: Array e -> Int -> ST s e
154− read ary i = check "read" ary i read
155− {-# INLINE read #-}
156−
157− -- | Write a mutable array. An invalid index results in a runtime
158− -- error.
159− write :: Array e -> Int -> ST s e
160− write ary i = check "write" ary i write
161− {-# INLINE write #-}
162−
16390-- | Freeze a mutable array. Do not mutate the 'MArray' afterwards!
164−unsafeFreeze :: MArray s e -> ST s (Array e)
165−
166−#if defined(__GLASGOW_HASKELL__)
167−
168−wORD16_SCALE :: Int# -> Int#
169−wORD16_SCALE n# = scale# *# n# where !(I# scale#) = SIZEOF_WORD16
91+unsafeFreeze :: MArray s -> ST s (Array)
17092
17193-- | Create an uninitialized mutable array.
172−unsafeNew :: forall s e. Elt e => Int -> ST s (MArray s e)
94+unsafeNew :: forall s. Int -> ST s (MArray s)
17395unsafeNew n = assert (n >= 0) . ST $ \s1# ->
174− case bytesInArray n (undefined :: e) of
96+ case bytesInArray n of
17597 len@(I# len#) ->
17698#if defined(BOUNDS_CHECKING)
17799 if len < 0 then error (show ("unsafeNew",len)) else
@@ -184,97 +106,57 @@ unsafeFreeze (MArray len mba#) = ST $ \s# ->
184106 (# s#, Array len (unsafeCoerce# mba#) #)
185107{-# INLINE unsafeFreeze #-}
186108
187−-- | Create a mutable array, with its elements initialized with the
188−-- given value.
189−new :: forall s e. Elt e => Int -> e -> ST s (MArray s e)
190−
191−#elif defined(__HUGS__)
192−
193−unsafeIndexArray :: Storable e => Array e -> Int -> e
194−unsafeIndexArray (Array off len arr) i =
195− assert (i >= 0 && i < len) $ readByteArray arr (off + i)
196−
197−unsafeReadMArray :: Storable e => MArray s e -> Int -> ST s e
198−unsafeReadMArray (MArray _len marr) i =
199− assert (i >= 0 && i < len) $ readMutableByteArray marr
200−
201−unsafeWriteMArray :: Storable e => MArray s e -> Int -> e -> ST s ()
202−unsafeWriteMArray (MArray len marr) i =
203− assert (i >= 0 && i < len) $ writeMutableByteArray marr
204−
205−-- | Create an uninitialized mutable array.
206−unsafeNew :: (Storable e) => Int -> ST s (MArray s e)
207−unsafeNew n = new undefined
208− where new :: (Storable e) => e -> ST s (MArray s e)
209− new unused = do
210− marr <- newMutableByteArray (n * sizeOf unused)
211− return (MArray n marr)
212−
213−unsafeFreeze (MArray len mba) = do
214− ba <- unsafeFreezeMutableByteArray mba
215− return (Array 0 len ba)
216−
217−-- | Create a mutable array, with its elements initialized with the
218−-- given value.
219−new :: (Storable e) => Int -> e -> ST s (MArray s e)
220−#endif
221−
222−new len initVal = do
223− marr <- unsafeNew len
224− sequence_ [unsafeWrite marr i initVal | i <- [0..len-1]]
225− return marr
226−
227−instance Elt Word16 where
228−#if defined(__GLASGOW_HASKELL__)
229−
230− bytesInArray (I# i#) _ = I# (wORD16_SCALE i#)
231− {-# INLINE bytesInArray #-}
232−
233− unsafeIndex (Array len ba#) i@(I# i#) =
234− CHECK_BOUNDS("unsafeIndex",len,i)
235− case indexWord16Array# ba# i# of r# -> (W16# r#)
236− {-# INLINE unsafeIndex #-}
237−
238− unsafeRead (MArray len mba#) i@(I# i#) = ST $ \s# ->
239− CHECK_BOUNDS("unsafeRead",len,i)
240− case readWord16Array# mba# i# s# of
241− (# s2#, r# #) -> (# s2#, W16# r# #)
242− {-# INLINE unsafeRead #-}
243−
244− unsafeWrite (MArray len marr#) i@(I# i#) (W16# e#) = ST $ \s1# ->
245− CHECK_BOUNDS("unsafeWrite",len,i)
246− case writeWord16Array# marr# i# e# s1# of
247− s2# -> (# s2#, () #)
248− {-# INLINE unsafeWrite #-}
249−
250−#elif defined(__HUGS__)
251−
252− bytesInArray n w = sizeOf w * n
253− unsafeIndex = unsafeIndexArray
254− unsafeRead = unsafeReadMArray
255− unsafeWrite = unsafeWriteMArray
256−
257−#endif
109+-- | Indicate how many bytes would be used for an array of the given
110+-- size.
111+bytesInArray :: Int -> Int
112+bytesInArray n = n `shiftL` 1
113+{-# INLINE bytesInArray #-}
114+
115+-- | Unchecked read of an immutable array. May return garbage or
116+-- crash on an out-of-bounds access.
117+unsafeIndex :: Array -> Int -> Word16
118+unsafeIndex (Array len ba#) i@(I# i#) =
119+ CHECK_BOUNDS("unsafeIndex",len,i)
120+ case indexWord16Array# ba# i# of r# -> (W16# r#)
121+{-# INLINE unsafeIndex #-}
122+
123+-- | Unchecked read of a mutable array. May return garbage or
124+-- crash on an out-of-bounds access.
125+unsafeRead :: MArray s -> Int -> ST s Word16
126+unsafeRead (MArray len mba#) i@(I# i#) = ST $ \s# ->
127+ CHECK_BOUNDS("unsafeRead",len,i)
128+ case readWord16Array# mba# i# s# of
129+ (# s2#, r# #) -> (# s2#, W16# r# #)
130+{-# INLINE unsafeRead #-}
131+
132+-- | Unchecked write of a mutable array. May return garbage or crash
133+-- on an out-of-bounds access.
134+unsafeWrite :: MArray s -> Int -> Word16 -> ST s ()
135+unsafeWrite (MArray len marr#) i@(I# i#) (W16# e#) = ST $ \s1# ->
136+ CHECK_BOUNDS("unsafeWrite",len,i)
137+ case writeWord16Array# marr# i# e# s1# of
138+ s2# -> (# s2#, () #)
139+{-# INLINE unsafeWrite #-}
258140
259141-- | Convert an immutable array to a list.
260−toList :: Elt e => Array e -> [e]
142+toList :: Array -> [Word16]
261143toList a = loop 0
262144 where loop i | i < len = unsafeIndex a i : loop (i+1)
263145 | otherwise = []
264146 len = length a
265147
266148-- | An empty immutable array.
267−empty :: Elt e => Array e
149+empty :: Array
268150empty = runST (unsafeNew 0 >>= unsafeFreeze)
269151
270152-- | Run an action in the ST monad and return an immutable array of
271153-- its result.
272−run :: Elt e => (forall s. ST s (MArray s e)) -> Array e
154+run :: (forall s. ST s (MArray s)) -> Array
273155run k = runST (k >>= unsafeFreeze)
274156
275157-- | Run an action in the ST monad and return an immutable array of
276158-- its result paired with whatever else the action returns.
277−run2 :: Elt e => (forall s. ST s (MArray s e, a)) -> (Array e, a)
159+run2 :: (forall s. ST s (MArray s, a)) -> (Array, a)
278160run2 k = runST (do
279161 (marr,b) <- k
280162 arr <- unsafeFreeze marr
@@ -282,8 +164,8 @@ run2 k = runST (do
282164
283165-- | Copy an array in its entirety. The destination array must be at
284166-- least as big as the source.
285−copy :: Elt e => MArray s e -- ^ source array
286− -> MArray s e -- ^ destination array
167+copy :: MArray s -- ^ source array
168+ -> MArray s -- ^ destination array
287169 -> ST s ()
288170copy src dest
289171 | length dest >= length src = copy_loop 0
@@ -297,8 +179,7 @@ copy src dest
297179{-# INLINE copy #-}
298180
299181-- | Unsafely copy the elements of an array.
300−unsafeCopy :: Elt e =>
301− MArray s e -> Int -> MArray s e -> Int -> Int -> ST s ()
182+unsafeCopy :: MArray s -> Int -> MArray s -> Int -> Int -> ST s ()
302183unsafeCopy src sidx dest didx count =
303184 assert (sidx + count <= length src) .
304185 assert (didx + count <= length dest) $
Data/Text/IO/Internal.hs+2−2
@@ -127,7 +127,7 @@ getSomeCharacters :: Handle__ -> CharBuffer -> IO CharBuffer
127127getSomeCharacters handle_@Handle__{..} buf@Buffer{..} =
128128 case bufferElems buf of
129129 -- buffer empty: read some more
130− 0 -> readTextDevice handle_ buf
130+ 0 -> {-# SCC "readTextDevice" #-} readTextDevice handle_ buf
131131
132132 -- if the buffer has a single '\r' in it and we're doing newline
133133 -- translation: read some more
@@ -145,7 +145,7 @@ getSomeCharacters handle_@Handle__{..} buf@Buffer{..} =
145145 return buf
146146
147147 -- buffer has some chars in it already: just return it
148− _otherwise -> return buf
148+ _otherwise -> {-# SCC "otherwise" #-} return buf
149149
150150-- | Read a single chunk of strict text from a buffer. Used by both
151151-- the strict and lazy implementations of hGetContents.
Data/Text/Internal.hs+3−4
@@ -31,17 +31,16 @@ module Data.Text.Internal
3131import Control.Exception (assert)
3232import qualified Data.Text.Array as A
3333import Data.Typeable (Typeable)
34−import Data.Word (Word16)
3534
3635-- | A space efficient, packed, unboxed Unicode text type.
3736data Text = Text
38− {-# UNPACK #-} !(A.Array Word16) -- payload
37+ {-# UNPACK #-} !A.Array -- payload
3938 {-# UNPACK #-} !Int -- offset
4039 {-# UNPACK #-} !Int -- length
4140 deriving (Typeable)
4241
4342-- | Smart constructor.
44−text :: A.Array Word16 -> Int -> Int -> Text
43+text :: A.Array -> Int -> Int -> Text
4544text arr off len =
4645 assert (len >= 0) .
4746 assert (off >= 0) .
@@ -59,7 +58,7 @@ empty = Text A.empty 0 0
5958
6059-- | Construct a 'Text' without invisibly pinning its byte array in
6160-- memory if its length has dwindled to zero.
62−textP :: A.Array Word16 -> Int -> Int -> Text
61+textP :: A.Array -> Int -> Int -> Text
6362textP arr off len | len == 0 = empty
6463 | otherwise = text arr off len
6564{-# INLINE textP #-}
Data/Text/Lazy/Builder.hs+9−11
@@ -38,7 +38,6 @@ import Data.Text.Internal (Text(..))
3838import Data.Text.Lazy.Internal (smallChunkSize)
3939import Data.Text.Unsafe (inlineInterleaveST)
4040import Data.Text.UnsafeShift (shiftR)
41−import Data.Word (Word16)
4241import Prelude hiding (map, putChar)
4342
4443import qualified Data.String as String
@@ -163,7 +162,7 @@ fromLazyText ts = flush `append` mapBuilder (L.toChunks ts ++)
163162------------------------------------------------------------------------
164163
165164-- Our internal buffer type
166−data Buffer s = Buffer {-# UNPACK #-} !(A.MArray s Word16)
165+data Buffer s = Buffer {-# UNPACK #-} !(A.MArray s)
167166 {-# UNPACK #-} !Int -- offset
168167 {-# UNPACK #-} !Int -- used units
169168 {-# UNPACK #-} !Int -- length left
@@ -240,11 +239,11 @@ ensureFree !n = withSize $ \ l ->
240239
241240-- | Ensure that @n@ many elements are available, and then use @f@ to
242241-- write some elements into the memory.
243−writeN :: Int -> (forall s. A.MArray s Word16 -> Int -> ST s ()) -> Builder
242+writeN :: Int -> (forall s. A.MArray s -> Int -> ST s ()) -> Builder
244243writeN n f = ensureFree n `append'` withBuffer (writeNBuffer n f)
245244{-# INLINE [0] writeN #-}
246245
247−writeNBuffer :: Int -> (A.MArray s Word16 -> Int -> ST s ()) -> (Buffer s)
246+writeNBuffer :: Int -> (A.MArray s -> Int -> ST s ()) -> (Buffer s)
248247 -> ST s (Buffer s)
249248writeNBuffer n f (Buffer p o u l) = do
250249 f p (o+u)
@@ -258,8 +257,7 @@ newBuffer size = do
258257{-# INLINE newBuffer #-}
259258
260259-- | Unsafely copy the elements of an array.
261−unsafeCopy :: A.Elt e =>
262− A.Array e -> Int -> A.MArray s e -> Int -> Int -> ST s ()
260+unsafeCopy :: A.Array -> Int -> A.MArray s -> Int -> Int -> ST s ()
263261unsafeCopy src sidx dest didx count =
264262 assert (sidx + count <= A.length src) .
265263 assert (didx + count <= A.length dest) $
@@ -273,7 +271,7 @@ unsafeCopy src sidx dest didx count =
273271
274272-- Write a character to the array, starting at the specified offset
275273-- @i@. Returns the number of elements written.
276−unsafeWrite :: A.MArray s Word16 -> Int -> Char -> ST s Int
274+unsafeWrite :: A.MArray s -> Int -> Char -> ST s Int
277275unsafeWrite marr i c
278276 | n < 0x10000 = do
279277 assert (i >= 0) . assert (i < A.length marr) $
@@ -302,13 +300,13 @@ append' (Builder f) (Builder g) = Builder (f . g)
302300
303301{-# RULES
304302
305−"append/writeN" forall a b (f::forall s. A.MArray s Word16 -> Int -> ST s ())
306− (g::forall s. A.MArray s Word16 -> Int -> ST s ()) ws.
303+"append/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
304+ (g::forall s. A.MArray s -> Int -> ST s ()) ws.
307305 append (writeN a f) (append (writeN b g) ws) =
308306 append (writeN (a+b) (\marr o -> f marr o >> g marr (o+a))) ws
309307
310−"writeN/writeN" forall a b (f::forall s. A.MArray s Word16 -> Int -> ST s ())
311− (g::forall s. A.MArray s Word16 -> Int -> ST s ()).
308+"writeN/writeN" forall a b (f::forall s. A.MArray s -> Int -> ST s ())
309+ (g::forall s. A.MArray s -> Int -> ST s ()).
312310 append (writeN a f) (writeN b g) =
313311 writeN (a+b) (\marr o -> f marr o >> g marr (o+a))
314312
Data/Text/UnsafeChar.hs+1−1
@@ -43,7 +43,7 @@ unsafeChr32 :: Word32 -> Char
4343unsafeChr32 (W32# w#) = C# (chr# (word2Int# w#))
4444{-# INLINE unsafeChr32 #-}
4545
46−unsafeWrite :: A.MArray s Word16 -> Int -> Char -> ST s Int
46+unsafeWrite :: A.MArray s -> Int -> Char -> ST s Int
4747unsafeWrite marr i c
4848 | n < 0x10000 = do
4949 assert (i >= 0) . assert (i < A.length marr) $