Advertisement
Guest User

Untitled

a guest
Aug 18th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.90 KB | None | 0 0
  1. {-# LANGUAGE BangPatterns #-}
  2. {-# LANGUAGE OverloadedStrings #-}
  3.  
  4. module Main (main) where
  5.  
  6. import Criterion.Main
  7. import Data.Char
  8. import qualified Data.Text as T
  9. import qualified Data.Text.Array as TA
  10. import qualified Data.Text.Internal as T
  11. import qualified Data.Text.Lazy as TL (Text, fromStrict)
  12. import Data.Bits
  13. import Data.Word
  14.  
  15. isAsciiLetter :: Char -> Bool
  16. isAsciiLetter c = isAsciiLower c || isAsciiUpper c
  17.  
  18. isAllowedStart :: Char -> Bool
  19. isAllowedStart c = c == '_' || isAsciiLetter c
  20.  
  21. data MangledSize = MangledSize
  22. { _unmangledChars :: !Int
  23. , _mangledWord16s :: !Int
  24. }
  25.  
  26. ord' :: Char -> Word16
  27. ord' = fromIntegral . ord
  28.  
  29. mangleIdentifier' :: T.Text -> Either String TL.Text
  30. mangleIdentifier' txt = case T.foldl' f (MangledSize 0 0) txt of
  31. MangledSize 0 _ -> Left "Empty identifier"
  32. MangledSize chars word16s
  33. | chars == word16s -> Right $! TL.fromStrict txt
  34. | otherwise -> Right $! TL.fromStrict $
  35. let !arr = TA.run $ do
  36. a <- TA.new word16s
  37. let poke !j !minj !x
  38. | j < minj = pure ()
  39. | otherwise = do
  40.  
  41. let !(!x', !r) = quotRem x 16
  42. -- let !x' = x `unsafeShiftR` 4
  43. -- let !r = x .&. 0xF
  44.  
  45. TA.unsafeWrite a j (fromIntegral $ ord $ intToDigit r)
  46. poke (j - 1) minj x'
  47. go !i t = case T.uncons t of
  48. Nothing -> pure ()
  49. Just (!c, !t')
  50. | isAllowedStart c || i > 0 && isDigit c -> TA.unsafeWrite a i (fromIntegral $ ord c) >> go (i + 1) t'
  51. | c == '$' -> do
  52. TA.unsafeWrite a i (ord' '$')
  53. TA.unsafeWrite a (i + 1) (ord' '$')
  54. go (i + 2) t'
  55. | ord c <= 0xFFFF -> do
  56. TA.unsafeWrite a i (ord' '$')
  57. TA.unsafeWrite a (i + 1) (ord' 'u')
  58. poke (i + 5) (i + 2) (ord c)
  59. go (i + 6) t'
  60. | otherwise -> do
  61. TA.unsafeWrite a i (ord' '$')
  62. TA.unsafeWrite a (i + 1) (ord' 'U')
  63. poke (i + 9) (i + 2) (ord c)
  64. go (i + 10) t'
  65. go 0 txt
  66. pure a
  67. in T.text arr 0 word16s
  68. where f :: MangledSize -> Char -> MangledSize
  69. f (MangledSize chars word16s) c
  70. | isAllowedStart c || chars > 0 && isDigit c = MangledSize (chars + 1) (word16s + 1)
  71. | c == '$' = MangledSize 1 (word16s + 2)
  72. | ord c > 0xFFFF = MangledSize 1 (word16s + 10)
  73. | otherwise = MangledSize 1 (word16s + 6)
  74.  
  75. criterionMain :: IO ()
  76. criterionMain = defaultMain [bench "mangling new" $ nf mangleIdentifier' "$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ "]
  77.  
  78. main :: IO ()
  79. main = criterionMain
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement