@@ -0,0 +1,146 @@
1+{-# LANGUAGE OverloadedStrings #-}
9+import qualified Data.ByteString.Short as S
10+import qualified Data.Map as Map
11+import qualified Data.Set as Set
12+import qualified Data.Text as Text
13+import qualified Data.Text.Encoding as Text
14+import Data.Word (Word8)
21+jsReservedWords :: Set.Set Text.Text
25+ , "NaN", "int", "for", "new", "try", "var", "let"
26+ , "null", "true", "eval", "byte", "char", "goto", "long", "case", "else", "this", "void", "with", "enum"
27+ , "false", "final", "float", "short", "break", "catch", "throw", "while", "class", "const", "super", "yield"
28+ , "double", "native", "throws", "delete", "return", "switch", "typeof", "export", "import", "public", "static"
29+ , "boolean", "default", "finally", "extends", "package", "private"
30+ , "Infinity", "abstract", "volatile", "function", "continue", "debugger", "function"
31+ , "undefined", "arguments", "transient", "interface", "protected"
32+ , "instanceof", "implements"
41+intToAscii :: Int -> S.ShortByteString
43+ if n < 53 then -- skip $ as a standalone name
47+ intToAsciiHelp (numStartBytes * numInnerBytes) allBadFields (n - 53)
50+intToAsciiHelp :: Int -> [BadFields] -> Int -> S.ShortByteString
51+intToAsciiHelp blockSize badFields n =
54+ if n < blockSize then
57+ intToAsciiHelp (blockSize * numInnerBytes) [] (n - blockSize)
59+ BadFields renamings : biggerBadFields ->
60+ let availableSize = blockSize - Map.size renamings in
61+ if n < availableSize then
62+ let name = unsafeIntToAscii n in
63+ Map.findWithDefault name name renamings
65+ intToAsciiHelp (blockSize * numInnerBytes) biggerBadFields (n - availableSize)
69+-- UNSAFE INT TO ASCII
72+unsafeIntToAscii :: Int -> S.ShortByteString
75+ (quotient, remainder) =
76+ quotRem n numStartBytes
78+ S.pack $ toByte remainder : unsafeIntToAsciiHelp quotient
81+unsafeIntToAsciiHelp :: Int -> [Word8]
82+unsafeIntToAsciiHelp n =
86+ let (quotient, remainder) = quotRem n numInnerBytes in
87+ toByte remainder : unsafeIntToAsciiHelp quotient
104+toByte :: Int -> Word8
106+ | n < 26 = fromIntegral (97 + n ) {- lower -}
107+ | n < 52 = fromIntegral (65 + n - 26) {- upper -}
108+ | n == 52 = 0x5F {- _ -}
109+ | n == 53 = 0x24 {- $ -}
110+ | n < 64 = fromIntegral (48 + n - 54) {- digit -}
111+ | True = error $ "cannot convert int " ++ show n ++ " to ASCII"
119+ BadFields { _renamings :: Renamings }
123+ Map.Map S.ShortByteString S.ShortByteString
126+allBadFields :: [BadFields]
130+ Map.alter (Just . addRenaming keyword) (Text.length keyword) dict
132+ Map.elems $ Set.foldr add Map.empty jsReservedWords
135+addRenaming :: Text.Text -> Maybe BadFields -> BadFields
136+addRenaming keyword maybeBadFields =
139+ numStartBytes * numInnerBytes ^ (Text.length keyword - 1) - 1
141+ case maybeBadFields of
143+ BadFields $ Map.singleton (S.toShort (Text.encodeUtf8 keyword)) (unsafeIntToAscii maxName)
145+ Just (BadFields renamings) ->
146+ BadFields $ Map.insert (S.toShort (Text.encodeUtf8 keyword)) (unsafeIntToAscii (maxName - Map.size renamings)) renamings