Delete all /* ! __GLASGOW_HASKELL__ */ code
[ghc.git] / compiler / utils / FastString.lhs
1 %
2 % (c) The University of Glasgow, 1997-2006
3 %
4 \begin{code}
5 {-# LANGUAGE BangPatterns, CPP, DeriveDataTypeable, MagicHash, UnboxedTuples #-}
6 {-# OPTIONS_GHC -O -funbox-strict-fields #-}
7 -- We always optimise this, otherwise performance of a non-optimised
8 -- compiler is severely affected
9
10 -- |
11 -- There are two principal string types used internally by GHC:
12 --
13 -- ['FastString']
14 --
15 --   * A compact, hash-consed, representation of character strings.
16 --   * Comparison is O(1), and you can get a 'Unique.Unique' from them.
17 --   * Generated by 'fsLit'.
18 --   * Turn into 'Outputable.SDoc' with 'Outputable.ftext'.
19 --
20 -- ['LitString']
21 --
22 --   * Just a wrapper for the @Addr#@ of a C string (@Ptr CChar@).
23 --   * Practically no operations.
24 --   * Outputing them is fast.
25 --   * Generated by 'sLit'.
26 --   * Turn into 'Outputable.SDoc' with 'Outputable.ptext'
27 --
28 -- Use 'LitString' unless you want the facilities of 'FastString'.
29 module FastString
30        (
31         -- * ByteString
32         fastStringToByteString,
33         mkFastStringByteString,
34         fastZStringToByteString,
35         unsafeMkByteString,
36         hashByteString,
37
38         -- * FastZString
39         FastZString,
40         hPutFZS,
41         zString,
42         lengthFZS,
43
44         -- * FastStrings
45         FastString(..),     -- not abstract, for now.
46
47         -- ** Construction
48         fsLit,
49         mkFastString,
50         mkFastStringBytes,
51         mkFastStringByteList,
52         mkFastStringForeignPtr,
53         mkFastString#,
54
55         -- ** Deconstruction
56         unpackFS,           -- :: FastString -> String
57         bytesFS,            -- :: FastString -> [Word8]
58
59         -- ** Encoding
60         zEncodeFS,
61
62         -- ** Operations
63         uniqueOfFS,
64         lengthFS,
65         nullFS,
66         appendFS,
67         headFS,
68         tailFS,
69         concatFS,
70         consFS,
71         nilFS,
72
73         -- ** Outputing
74         hPutFS,
75
76         -- ** Internal
77         getFastStringTable,
78         hasZEncoding,
79
80         -- * LitStrings
81         LitString,
82
83         -- ** Construction
84         sLit,
85         mkLitString#,
86         mkLitString,
87
88         -- ** Deconstruction
89         unpackLitString,
90
91         -- ** Operations
92         lengthLS
93        ) where
94
95 #include "HsVersions.h"
96
97 import Encoding
98 import FastTypes
99 import FastFunctions
100 import Panic
101 import Util
102
103 import Control.Monad
104 import Data.ByteString (ByteString)
105 import qualified Data.ByteString          as BS
106 import qualified Data.ByteString.Char8    as BSC
107 import qualified Data.ByteString.Internal as BS
108 import qualified Data.ByteString.Unsafe   as BS
109 import Foreign.C
110 import ExtsCompat46
111 import System.IO
112 import System.IO.Unsafe ( unsafePerformIO )
113 import Data.Data
114 import Data.IORef       ( IORef, newIORef, readIORef, atomicModifyIORef )
115 import Data.Maybe       ( isJust )
116 import Data.Char
117 import Data.List        ( elemIndex )
118
119 import GHC.IO           ( IO(..), unsafeDupablePerformIO )
120
121 import Foreign.Safe
122
123 #if STAGE >= 2
124 import GHC.Conc.Sync    (sharedCAF)
125 #endif
126
127 import GHC.Base         ( unpackCString# )
128
129 #define hASH_TBL_SIZE          4091
130 #define hASH_TBL_SIZE_UNBOXED  4091#
131
132
133 fastStringToByteString :: FastString -> ByteString
134 fastStringToByteString f = fs_bs f
135
136 fastZStringToByteString :: FastZString -> ByteString
137 fastZStringToByteString (FastZString bs) = bs
138
139 -- This will drop information if any character > '\xFF'
140 unsafeMkByteString :: String -> ByteString
141 unsafeMkByteString = BSC.pack
142
143 hashByteString :: ByteString -> Int
144 hashByteString bs
145     = inlinePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, len) ->
146       return $ hashStr (castPtr ptr) len
147
148 -- -----------------------------------------------------------------------------
149
150 newtype FastZString = FastZString ByteString
151
152 hPutFZS :: Handle -> FastZString -> IO ()
153 hPutFZS handle (FastZString bs) = BS.hPut handle bs
154
155 zString :: FastZString -> String
156 zString (FastZString bs) =
157     inlinePerformIO $ BS.unsafeUseAsCStringLen bs peekCAStringLen
158
159 lengthFZS :: FastZString -> Int
160 lengthFZS (FastZString bs) = BS.length bs
161
162 mkFastZStringString :: String -> FastZString
163 mkFastZStringString str = FastZString (BSC.pack str)
164
165 -- -----------------------------------------------------------------------------
166
167 {-|
168 A 'FastString' is an array of bytes, hashed to support fast O(1)
169 comparison.  It is also associated with a character encoding, so that
170 we know how to convert a 'FastString' to the local encoding, or to the
171 Z-encoding used by the compiler internally.
172
173 'FastString's support a memoized conversion to the Z-encoding via zEncodeFS.
174 -}
175
176 data FastString = FastString {
177       uniq    :: {-# UNPACK #-} !Int, -- unique id
178       n_chars :: {-# UNPACK #-} !Int, -- number of chars
179       fs_bs   :: {-# UNPACK #-} !ByteString,
180       fs_ref  :: {-# UNPACK #-} !(IORef (Maybe FastZString))
181   } deriving Typeable
182
183 instance Eq FastString where
184   f1 == f2  =  uniq f1 == uniq f2
185
186 instance Ord FastString where
187     -- Compares lexicographically, not by unique
188     a <= b = case cmpFS a b of { LT -> True;  EQ -> True;  GT -> False }
189     a <  b = case cmpFS a b of { LT -> True;  EQ -> False; GT -> False }
190     a >= b = case cmpFS a b of { LT -> False; EQ -> True;  GT -> True  }
191     a >  b = case cmpFS a b of { LT -> False; EQ -> False; GT -> True  }
192     max x y | x >= y    =  x
193             | otherwise =  y
194     min x y | x <= y    =  x
195             | otherwise =  y
196     compare a b = cmpFS a b
197
198 instance Show FastString where
199    show fs = show (unpackFS fs)
200
201 instance Data FastString where
202   -- don't traverse?
203   toConstr _   = abstractConstr "FastString"
204   gunfold _ _  = error "gunfold"
205   dataTypeOf _ = mkNoRepType "FastString"
206
207 cmpFS :: FastString -> FastString -> Ordering
208 cmpFS f1@(FastString u1 _ _ _) f2@(FastString u2 _ _ _) =
209   if u1 == u2 then EQ else
210   compare (fastStringToByteString f1) (fastStringToByteString f2)
211
212 foreign import ccall unsafe "ghc_memcmp"
213   memcmp :: Ptr a -> Ptr b -> Int -> IO Int
214
215 -- -----------------------------------------------------------------------------
216 -- Construction
217
218 {-
219 Internally, the compiler will maintain a fast string symbol table, providing
220 sharing and fast comparison. Creation of new @FastString@s then covertly does a
221 lookup, re-using the @FastString@ if there was a hit.
222
223 The design of the FastString hash table allows for lockless concurrent reads
224 and updates to multiple buckets with low synchronization overhead.
225
226 See Note [Updating the FastString table] on how it's updated.
227 -}
228 data FastStringTable =
229  FastStringTable
230     {-# UNPACK #-} !(IORef Int)  -- the unique ID counter shared with all buckets
231     (MutableArray# RealWorld (IORef [FastString])) -- the array of mutable buckets
232
233 string_table :: FastStringTable
234 {-# NOINLINE string_table #-}
235 string_table = unsafePerformIO $ do
236   uid <- newIORef 603979776 -- ord '$' * 0x01000000
237   tab <- IO $ \s1# -> case newArray# hASH_TBL_SIZE_UNBOXED (panic "string_table") s1# of
238                           (# s2#, arr# #) ->
239                               (# s2#, FastStringTable uid arr# #)
240   forM_ [0.. hASH_TBL_SIZE-1] $ \i -> do
241      bucket <- newIORef []
242      updTbl tab i bucket
243
244   -- use the support wired into the RTS to share this CAF among all images of
245   -- libHSghc
246 #if STAGE < 2
247   return tab
248 #else
249   sharedCAF tab getOrSetLibHSghcFastStringTable
250
251 -- from the RTS; thus we cannot use this mechanism when STAGE<2; the previous
252 -- RTS might not have this symbol
253 foreign import ccall unsafe "getOrSetLibHSghcFastStringTable"
254   getOrSetLibHSghcFastStringTable :: Ptr a -> IO (Ptr a)
255 #endif
256
257 {-
258
259 We include the FastString table in the `sharedCAF` mechanism because we'd like
260 FastStrings created by a Core plugin to have the same uniques as corresponding
261 strings created by the host compiler itself.  For example, this allows plugins
262 to lookup known names (eg `mkTcOcc "MySpecialType"`) in the GlobalRdrEnv or
263 even re-invoke the parser.
264
265 In particular, the following little sanity test was failing in a plugin
266 prototyping safe newtype-coercions: GHC.NT.Type.NT was imported, but could not
267 be looked up /by the plugin/.
268
269    let rdrName = mkModuleName "GHC.NT.Type" `mkRdrQual` mkTcOcc "NT"
270    putMsgS $ showSDoc dflags $ ppr $ lookupGRE_RdrName rdrName $ mg_rdr_env guts
271
272 `mkTcOcc` involves the lookup (or creation) of a FastString.  Since the
273 plugin's FastString.string_table is empty, constructing the RdrName also
274 allocates new uniques for the FastStrings "GHC.NT.Type" and "NT".  These
275 uniques are almost certainly unequal to the ones that the host compiler
276 originally assigned to those FastStrings.  Thus the lookup fails since the
277 domain of the GlobalRdrEnv is affected by the RdrName's OccName's FastString's
278 unique.
279
280 The old `reinitializeGlobals` mechanism is enough to provide the plugin with
281 read-access to the table, but it insufficient in the general case where the
282 plugin may allocate FastStrings. This mutates the supply for the FastStrings'
283 unique, and that needs to be propagated back to the compiler's instance of the
284 global variable.  Such propagation is beyond the `reinitializeGlobals`
285 mechanism.
286
287 Maintaining synchronization of the two instances of this global is rather
288 difficult because of the uses of `unsafePerformIO` in this module.  Not
289 synchronizing them risks breaking the rather major invariant that two
290 FastStrings with the same unique have the same string. Thus we use the
291 lower-level `sharedCAF` mechanism that relies on Globals.c.
292
293 -}
294
295 lookupTbl :: FastStringTable -> Int -> IO (IORef [FastString])
296 lookupTbl (FastStringTable _ arr#) (I# i#) =
297   IO $ \ s# -> readArray# arr# i# s#
298
299 updTbl :: FastStringTable -> Int -> IORef [FastString] -> IO ()
300 updTbl (FastStringTable _uid arr#) (I# i#) ls = do
301   (IO $ \ s# -> case writeArray# arr# i# ls s# of { s2# -> (# s2#, () #) })
302
303 mkFastString# :: Addr# -> FastString
304 mkFastString# a# = mkFastStringBytes ptr (ptrStrLength ptr)
305   where ptr = Ptr a#
306
307 {- Note [Updating the FastString table]
308
309 The procedure goes like this:
310
311 1. Read the relevant bucket and perform a look up of the string.
312 2. If it exists, return it.
313 3. Otherwise grab a unique ID, create a new FastString and atomically attempt
314    to update the relevant bucket with this FastString:
315
316    * Double check that the string is not in the bucket. Another thread may have
317      inserted it while we were creating our string.
318    * Return the existing FastString if it exists. The one we preemptively
319      created will get GCed.
320    * Otherwise, insert and return the string we created.
321 -}
322
323 {- Note [Double-checking the bucket]
324
325 It is not necessary to check the entire bucket the second time. We only have to
326 check the strings that are new to the bucket since the last time we read it.
327 -}
328
329 mkFastStringWith :: (Int -> IO FastString) -> Ptr Word8 -> Int -> IO FastString
330 mkFastStringWith mk_fs !ptr !len = do
331     let hash = hashStr ptr len
332     bucket <- lookupTbl string_table hash
333     ls1 <- readIORef bucket
334     res <- bucket_match ls1 len ptr
335     case res of
336         Just v  -> return v
337         Nothing -> do
338             n <- get_uid
339             new_fs <- mk_fs n
340
341             atomicModifyIORef bucket $ \ls2 ->
342                 -- Note [Double-checking the bucket]
343                 let delta_ls = case ls1 of
344                         []  -> ls2
345                         l:_ -> case l `elemIndex` ls2 of
346                             Nothing  -> panic "mkFastStringWith"
347                             Just idx -> take idx ls2
348
349                 -- NB: Might as well use inlinePerformIO, since the call to
350                 -- bucket_match doesn't perform any IO that could be floated
351                 -- out of this closure or erroneously duplicated.
352                 in case inlinePerformIO (bucket_match delta_ls len ptr) of
353                     Nothing -> (new_fs:ls2, new_fs)
354                     Just fs -> (ls2,fs)
355   where
356     !(FastStringTable uid _arr) = string_table
357
358     get_uid = atomicModifyIORef uid $ \n -> (n+1,n)
359
360 mkFastStringBytes :: Ptr Word8 -> Int -> FastString
361 mkFastStringBytes !ptr !len =
362     -- NB: Might as well use unsafeDupablePerformIO, since mkFastStringWith is
363     -- idempotent.
364     unsafeDupablePerformIO $
365         mkFastStringWith (copyNewFastString ptr len) ptr len
366
367 -- | Create a 'FastString' from an existing 'ForeignPtr'; the difference
368 -- between this and 'mkFastStringBytes' is that we don't have to copy
369 -- the bytes if the string is new to the table.
370 mkFastStringForeignPtr :: Ptr Word8 -> ForeignPtr Word8 -> Int -> IO FastString
371 mkFastStringForeignPtr ptr !fp len
372     = mkFastStringWith (mkNewFastString fp ptr len) ptr len
373
374 -- | Create a 'FastString' from an existing 'ForeignPtr'; the difference
375 -- between this and 'mkFastStringBytes' is that we don't have to copy
376 -- the bytes if the string is new to the table.
377 mkFastStringByteString :: ByteString -> FastString
378 mkFastStringByteString bs =
379     inlinePerformIO $
380       BS.unsafeUseAsCStringLen bs $ \(ptr, len) -> do
381         let ptr' = castPtr ptr
382         mkFastStringWith (mkNewFastStringByteString bs ptr' len) ptr' len
383
384 -- | Creates a UTF-8 encoded 'FastString' from a 'String'
385 mkFastString :: String -> FastString
386 mkFastString str =
387   inlinePerformIO $ do
388     let l = utf8EncodedLength str
389     buf <- mallocForeignPtrBytes l
390     withForeignPtr buf $ \ptr -> do
391       utf8EncodeString ptr str
392       mkFastStringForeignPtr ptr buf l
393
394 -- | Creates a 'FastString' from a UTF-8 encoded @[Word8]@
395 mkFastStringByteList :: [Word8] -> FastString
396 mkFastStringByteList str =
397   inlinePerformIO $ do
398     let l = Prelude.length str
399     buf <- mallocForeignPtrBytes l
400     withForeignPtr buf $ \ptr -> do
401       pokeArray (castPtr ptr) str
402       mkFastStringForeignPtr ptr buf l
403
404 -- | Creates a Z-encoded 'FastString' from a 'String'
405 mkZFastString :: String -> FastZString
406 mkZFastString = mkFastZStringString
407
408 bucket_match :: [FastString] -> Int -> Ptr Word8 -> IO (Maybe FastString)
409 bucket_match [] _ _ = return Nothing
410 bucket_match (v@(FastString _ _ bs _):ls) len ptr
411       | len == BS.length bs = do
412          b <- BS.unsafeUseAsCString bs $ \buf ->
413              cmpStringPrefix ptr (castPtr buf) len
414          if b then return (Just v)
415               else bucket_match ls len ptr
416       | otherwise =
417          bucket_match ls len ptr
418
419 mkNewFastString :: ForeignPtr Word8 -> Ptr Word8 -> Int -> Int
420                 -> IO FastString
421 mkNewFastString fp ptr len uid = do
422   ref <- newIORef Nothing
423   n_chars <- countUTF8Chars ptr len
424   return (FastString uid n_chars (BS.fromForeignPtr fp 0 len) ref)
425
426 mkNewFastStringByteString :: ByteString -> Ptr Word8 -> Int -> Int
427                           -> IO FastString
428 mkNewFastStringByteString bs ptr len uid = do
429   ref <- newIORef Nothing
430   n_chars <- countUTF8Chars ptr len
431   return (FastString uid n_chars bs ref)
432
433 copyNewFastString :: Ptr Word8 -> Int -> Int -> IO FastString
434 copyNewFastString ptr len uid = do
435   fp <- copyBytesToForeignPtr ptr len
436   ref <- newIORef Nothing
437   n_chars <- countUTF8Chars ptr len
438   return (FastString uid n_chars (BS.fromForeignPtr fp 0 len) ref)
439
440 copyBytesToForeignPtr :: Ptr Word8 -> Int -> IO (ForeignPtr Word8)
441 copyBytesToForeignPtr ptr len = do
442   fp <- mallocForeignPtrBytes len
443   withForeignPtr fp $ \ptr' -> copyBytes ptr' ptr len
444   return fp
445
446 cmpStringPrefix :: Ptr Word8 -> Ptr Word8 -> Int -> IO Bool
447 cmpStringPrefix ptr1 ptr2 len =
448  do r <- memcmp ptr1 ptr2 len
449     return (r == 0)
450
451
452 hashStr  :: Ptr Word8 -> Int -> Int
453  -- use the Addr to produce a hash value between 0 & m (inclusive)
454 hashStr (Ptr a#) (I# len#) = loop 0# 0#
455    where
456     loop h n | n ExtsCompat46.==# len# = I# h
457              | otherwise  = loop h2 (n ExtsCompat46.+# 1#)
458           where !c = ord# (indexCharOffAddr# a# n)
459                 !h2 = (c ExtsCompat46.+# (h ExtsCompat46.*# 128#)) `remInt#`
460                       hASH_TBL_SIZE#
461
462 -- -----------------------------------------------------------------------------
463 -- Operations
464
465 -- | Returns the length of the 'FastString' in characters
466 lengthFS :: FastString -> Int
467 lengthFS f = n_chars f
468
469 -- | Returns @True@ if this 'FastString' is not Z-encoded but already has
470 -- a Z-encoding cached (used in producing stats).
471 hasZEncoding :: FastString -> Bool
472 hasZEncoding (FastString _ _ _ ref) =
473       inlinePerformIO $ do
474         m <- readIORef ref
475         return (isJust m)
476
477 -- | Returns @True@ if the 'FastString' is empty
478 nullFS :: FastString -> Bool
479 nullFS f = BS.null (fs_bs f)
480
481 -- | Unpacks and decodes the FastString
482 unpackFS :: FastString -> String
483 unpackFS (FastString _ _ bs _) =
484   inlinePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, len) ->
485         utf8DecodeString (castPtr ptr) len
486
487 -- | Gives the UTF-8 encoded bytes corresponding to a 'FastString'
488 bytesFS :: FastString -> [Word8]
489 bytesFS fs = BS.unpack $ fastStringToByteString fs
490
491 -- | Returns a Z-encoded version of a 'FastString'.  This might be the
492 -- original, if it was already Z-encoded.  The first time this
493 -- function is applied to a particular 'FastString', the results are
494 -- memoized.
495 --
496 zEncodeFS :: FastString -> FastZString
497 zEncodeFS fs@(FastString _ _ _ ref) =
498       inlinePerformIO $ do
499         m <- readIORef ref
500         case m of
501           Just zfs -> return zfs
502           Nothing -> do
503             atomicModifyIORef ref $ \m' -> case m' of
504               Nothing  -> let zfs = mkZFastString (zEncodeString (unpackFS fs))
505                           in (Just zfs, zfs)
506               Just zfs -> (m', zfs)
507
508 appendFS :: FastString -> FastString -> FastString
509 appendFS fs1 fs2 = mkFastStringByteString
510                  $ BS.append (fastStringToByteString fs1)
511                              (fastStringToByteString fs2)
512
513 concatFS :: [FastString] -> FastString
514 concatFS ls = mkFastString (Prelude.concat (map unpackFS ls)) -- ToDo: do better
515
516 headFS :: FastString -> Char
517 headFS (FastString _ 0 _ _) = panic "headFS: Empty FastString"
518 headFS (FastString _ _ bs _) =
519   inlinePerformIO $ BS.unsafeUseAsCString bs $ \ptr ->
520          return (fst (utf8DecodeChar (castPtr ptr)))
521
522 tailFS :: FastString -> FastString
523 tailFS (FastString _ 0 _ _) = panic "tailFS: Empty FastString"
524 tailFS (FastString _ _ bs _) =
525     inlinePerformIO $ BS.unsafeUseAsCString bs $ \ptr ->
526     do let (_, n) = utf8DecodeChar (castPtr ptr)
527        return $! mkFastStringByteString (BS.drop n bs)
528
529 consFS :: Char -> FastString -> FastString
530 consFS c fs = mkFastString (c : unpackFS fs)
531
532 uniqueOfFS :: FastString -> FastInt
533 uniqueOfFS (FastString u _ _ _) = iUnbox u
534
535 nilFS :: FastString
536 nilFS = mkFastString ""
537
538 -- -----------------------------------------------------------------------------
539 -- Stats
540
541 getFastStringTable :: IO [[FastString]]
542 getFastStringTable = do
543   buckets <- forM [0.. hASH_TBL_SIZE-1] $ \idx -> do
544     bucket <- lookupTbl string_table idx
545     readIORef bucket
546   return buckets
547
548 -- -----------------------------------------------------------------------------
549 -- Outputting 'FastString's
550
551 -- |Outputs a 'FastString' with /no decoding at all/, that is, you
552 -- get the actual bytes in the 'FastString' written to the 'Handle'.
553 hPutFS :: Handle -> FastString -> IO ()
554 hPutFS handle fs = BS.hPut handle $ fastStringToByteString fs
555
556 -- ToDo: we'll probably want an hPutFSLocal, or something, to output
557 -- in the current locale's encoding (for error messages and suchlike).
558
559 -- -----------------------------------------------------------------------------
560 -- LitStrings, here for convenience only.
561
562 -- hmm, not unboxed (or rather FastPtr), interesting
563 --a.k.a. Ptr CChar, Ptr Word8, Ptr (), hmph.  We don't
564 --really care about C types in naming, where we can help it.
565 type LitString = Ptr Word8
566 --Why do we recalculate length every time it's requested?
567 --If it's commonly needed, we should perhaps have
568 --data LitString = LitString {-#UNPACK#-}!(FastPtr Word8) {-#UNPACK#-}!FastInt
569
570 mkLitString# :: Addr# -> LitString
571 mkLitString# a# = Ptr a#
572 --can/should we use FastTypes here?
573 --Is this likely to be memory-preserving if only used on constant strings?
574 --should we inline it? If lucky, that would make a CAF that wouldn't
575 --be computationally repeated... although admittedly we're not
576 --really intending to use mkLitString when __GLASGOW_HASKELL__...
577 --(I wonder, is unicode / multi-byte characters allowed in LitStrings
578 -- at all?)
579 {-# INLINE mkLitString #-}
580 mkLitString :: String -> LitString
581 mkLitString s =
582  unsafePerformIO (do
583    p <- mallocBytes (length s + 1)
584    let
585      loop :: Int -> String -> IO ()
586      loop !n [] = pokeByteOff p n (0 :: Word8)
587      loop n (c:cs) = do
588         pokeByteOff p n (fromIntegral (ord c) :: Word8)
589         loop (1+n) cs
590    loop 0 s
591    return p
592  )
593
594 unpackLitString :: LitString -> String
595 unpackLitString p_ = case pUnbox p_ of
596  p -> unpack (_ILIT(0))
597   where
598     unpack n = case indexWord8OffFastPtrAsFastChar p n of
599       ch -> if ch `eqFastChar` _CLIT('\0')
600             then [] else cBox ch : unpack (n +# _ILIT(1))
601
602 lengthLS :: LitString -> Int
603 lengthLS = ptrStrLength
604
605 -- for now, use a simple String representation
606 --no, let's not do that right now - it's work in other places
607 #if 0
608 type LitString = String
609
610 mkLitString :: String -> LitString
611 mkLitString = id
612
613 unpackLitString :: LitString -> String
614 unpackLitString = id
615
616 lengthLS :: LitString -> Int
617 lengthLS = length
618
619 #endif
620
621 -- -----------------------------------------------------------------------------
622 -- under the carpet
623
624 foreign import ccall unsafe "ghc_strlen"
625   ptrStrLength :: Ptr Word8 -> Int
626
627 {-# NOINLINE sLit #-}
628 sLit :: String -> LitString
629 sLit x  = mkLitString x
630
631 {-# NOINLINE fsLit #-}
632 fsLit :: String -> FastString
633 fsLit x = mkFastString x
634
635 {-# RULES "slit"
636     forall x . sLit  (unpackCString# x) = mkLitString#  x #-}
637 {-# RULES "fslit"
638     forall x . fsLit (unpackCString# x) = mkFastString# x #-}
639 \end{code}