1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript.Name
23import qualified Data.ByteString.Builder as B
24import qualified Data.ByteString.Short as S
25import qualified Data.List as List
26import Data.Monoid ((<>))
28import qualified Data.Map as Map
29import qualified Data.Set as Set
30import qualified Data.Text as Text
31import qualified Data.Text.Encoding as Text
32import Data.Word (Word8)
34import qualified AST.Module.Name as ModuleName
35import qualified Elm.Name as N
36import qualified Elm.Package as Pkg
44 Name { toBuilder :: B.Builder }
53 | Prod Target ShortFieldNames
56data Target = Client | Server
63isServer :: Mode -> Bool
66 Debug target -> isServerHelp target
67 Prod target _ -> isServerHelp target
70isServerHelp :: Target -> Bool
72 case target of { Client -> False ; Server -> True }
81 Name (B.shortByteString (intToAscii n))
84fromLocal :: N.Name -> Name
86 if Set.member name reservedNames then
87 Name ("_" <> N.toBuilder name)
89 Name (N.toBuilder name)
92fromGlobal :: ModuleName.Canonical -> N.Name -> Name
93fromGlobal (ModuleName.Canonical (Pkg.Name user project) home) name =
95 Text.encodeUtf8Builder (Text.replace "-" "_" user)
96 <> "$" <> Text.encodeUtf8Builder (Text.replace "-" "_" project) -- TODO store this in a better way
97 <> "$" <> N.toBuilder home
98 <> "$" <> N.toBuilder name
101fromCycle :: ModuleName.Canonical -> N.Name -> Name
102fromCycle (ModuleName.Canonical (Pkg.Name user project) home) name =
104 Text.encodeUtf8Builder (Text.replace "-" "_" user)
105 <> "$" <> Text.encodeUtf8Builder (Text.replace "-" "_" project) -- TODO store this in a better way
106 <> "$" <> N.toBuilder home
107 <> "$cyclic$" <> N.toBuilder name
110fromKernel :: N.Name -> N.Name -> Name
111fromKernel home name =
112 Name ("_" <> N.toBuilder home <> "_" <> N.toBuilder name)
115fromField :: Mode -> N.Name -> Name
119 Name (N.toBuilder name)
129makeLabel :: N.Name -> Int -> Name
130makeLabel name index =
131 Name (N.toBuilder name <> "$" <> B.intDec index)
134makeTemp :: N.Name -> Name
136 Name ("$temp$" <> N.toBuilder name)
141 Name (N.toBuilder N.dollar)
145-- SHORTEN FIELD NAMES
148shortenFieldNames :: Map.Map N.Name Int -> ShortFieldNames
149shortenFieldNames frequencies =
150 Map.foldr addToShortNames Map.empty $
151 Map.foldrWithKey addToBuckets Map.empty frequencies
154addToBuckets :: N.Name -> Int -> Map.Map Int [N.Name] -> Map.Map Int [N.Name]
155addToBuckets field frequency buckets =
156 -- TODO try using an IntMap for buckets
157 Map.insertWith (++) frequency [field] buckets
160addToShortNames :: [N.Name] -> ShortFieldNames -> ShortFieldNames
161addToShortNames fields shortNames =
162 List.foldl' addField shortNames fields
165addField :: ShortFieldNames -> N.Name -> ShortFieldNames
166addField shortNames field =
167 let rename = fromInt (Map.size shortNames) in
168 Map.insert field rename shortNames
175{-# NOINLINE reservedNames #-}
176reservedNames :: Set.Set N.Name
178 Set.union jsReservedWords elmReservedWords
181jsReservedWords :: Set.Set N.Name
185 , "NaN", "int", "for", "new", "try", "var", "let"
186 , "null", "true", "eval", "byte", "char", "goto", "long", "case", "else", "this", "void", "with", "enum"
187 , "false", "final", "float", "short", "break", "catch", "throw", "while", "class", "const", "super", "yield"
188 , "double", "native", "throws", "delete", "return", "switch", "typeof", "export", "import", "public", "static"
189 , "boolean", "default", "finally", "extends", "package", "private"
190 , "Infinity", "abstract", "volatile", "function", "continue", "debugger", "function"
191 , "undefined", "arguments", "transient", "interface", "protected"
192 , "instanceof", "implements"
197elmReservedWords :: Set.Set N.Name
200 [ "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
201 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
209intToAscii :: Int -> S.ShortByteString
211 if n < 53 then -- skip $ as a standalone name
215 intToAsciiHelp (numStartBytes * numInnerBytes) allBadFields (n - 53)
218intToAsciiHelp :: Int -> [BadFields] -> Int -> S.ShortByteString
219intToAsciiHelp blockSize badFields n =
222 if n < blockSize then
225 intToAsciiHelp (blockSize * numInnerBytes) [] (n - blockSize)
227 BadFields renamings : biggerBadFields ->
228 let availableSize = blockSize - Map.size renamings in
229 if n < availableSize then
230 let name = unsafeIntToAscii n in
231 Map.findWithDefault name name renamings
233 intToAsciiHelp (blockSize * numInnerBytes) biggerBadFields (n - availableSize)
237-- UNSAFE INT TO ASCII
240unsafeIntToAscii :: Int -> S.ShortByteString
243 (quotient, remainder) =
244 quotRem n numStartBytes
246 S.pack $ toByte remainder : unsafeIntToAsciiHelp quotient
249unsafeIntToAsciiHelp :: Int -> [Word8]
250unsafeIntToAsciiHelp n =
254 let (quotient, remainder) = quotRem n numInnerBytes in
255 toByte remainder : unsafeIntToAsciiHelp quotient
272toByte :: Int -> Word8
274 | n < 26 = fromIntegral (97 + n ) {- lower -}
275 | n < 52 = fromIntegral (65 + n - 26) {- upper -}
276 | n == 53 = 95 {- _ -}
277 | n == 54 = 36 {- $ -}
278 | n < 64 = fromIntegral (48 + n - 54) {- digit -}
279 | True = error $ "cannot convert int " ++ show n ++ " to ASCII"
287 BadFields { _renamings :: Renamings }
291 Map.Map S.ShortByteString S.ShortByteString
294allBadFields :: [BadFields]
298 Map.alter (Just . addRenaming keyword) (N.length keyword) dict
300 Map.elems $ Set.foldr add Map.empty jsReservedWords
303addRenaming :: N.Name -> Maybe BadFields -> BadFields
304addRenaming keyword maybeBadFields =
307 numStartBytes * numInnerBytes ^ (N.length keyword - 1) - 1
309 case maybeBadFields of
311 BadFields $ Map.singleton (N.toShort keyword) (unsafeIntToAscii maxName)
313 Just (BadFields renamings) ->
314 BadFields $ Map.insert (N.toShort keyword) (unsafeIntToAscii (maxName - Map.size renamings)) renamings
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list