1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript.Name
27import qualified Data.ByteString.Builder as B
28import qualified Data.ByteString.Short as S
29import qualified Data.List as List
30import Data.Monoid ((<>))
32import qualified Data.Map as Map
33import qualified Data.Set as Set
34import qualified Data.Text as Text
35import qualified Data.Text.Encoding as Text
36import Data.Word (Word8)
38import qualified AST.Module.Name as ModuleName
39import qualified Data.Index as Index
40import qualified Elm.Name as N
41import qualified Elm.Package as Pkg
49 Name { toBuilder :: B.Builder }
58 | Prod Target ShortFieldNames
61data Target = Client | Server
73isServer :: Mode -> Bool
76 Dev target _ -> isServerHelp target
77 Prod target _ -> isServerHelp target
80isServerHelp :: Target -> Bool
82 case target of { Client -> False ; Server -> True }
89fromIndex :: Index.ZeroBased -> Name
91 fromInt (Index.toMachine index)
96 Name (B.shortByteString (intToAscii n))
99fromLocal :: N.Name -> Name
101 if Set.member name reservedNames then
102 Name ("_" <> N.toBuilder name)
104 Name (N.toBuilder name)
107fromGlobal :: ModuleName.Canonical -> N.Name -> Name
108fromGlobal (ModuleName.Canonical (Pkg.Name user project) home) name =
110 Text.encodeUtf8Builder (Text.replace "-" "_" user)
111 <> "$" <> Text.encodeUtf8Builder (Text.replace "-" "_" project) -- TODO store this in a better way
112 <> "$" <> N.toDotlessBuilder home
113 <> "$" <> N.toBuilder name
116fromCycle :: ModuleName.Canonical -> N.Name -> Name
117fromCycle (ModuleName.Canonical (Pkg.Name user project) home) name =
119 Text.encodeUtf8Builder (Text.replace "-" "_" user)
120 <> "$" <> Text.encodeUtf8Builder (Text.replace "-" "_" project) -- TODO store this in a better way
121 <> "$" <> N.toDotlessBuilder home
122 <> "$cyclic$" <> N.toBuilder name
125fromKernel :: N.Name -> N.Name -> Name
126fromKernel home name =
127 Name ("_" <> N.toBuilder home <> "_" <> N.toBuilder name)
130fromField :: Mode -> N.Name -> Name
134 Name (N.toBuilder name)
146 Name ("F" <> B.intDec n)
151 Name ("A" <> B.intDec n)
154makeLabel :: N.Name -> Int -> Name
155makeLabel name index =
156 Name (N.toBuilder name <> "$" <> B.intDec index)
159makeTemp :: N.Name -> Name
161 Name ("$temp$" <> N.toBuilder name)
166 Name (N.toBuilder N.dollar)
170-- SHORTEN FIELD NAMES
173shortenFieldNames :: Map.Map N.Name Int -> ShortFieldNames
174shortenFieldNames frequencies =
175 Map.foldr addToShortNames Map.empty $
176 Map.foldrWithKey addToBuckets Map.empty frequencies
179addToBuckets :: N.Name -> Int -> Map.Map Int [N.Name] -> Map.Map Int [N.Name]
180addToBuckets field frequency buckets =
181 -- TODO try using an IntMap for buckets
182 Map.insertWith (++) frequency [field] buckets
185addToShortNames :: [N.Name] -> ShortFieldNames -> ShortFieldNames
186addToShortNames fields shortNames =
187 List.foldl' addField shortNames fields
190addField :: ShortFieldNames -> N.Name -> ShortFieldNames
191addField shortNames field =
192 let rename = fromInt (Map.size shortNames) in
193 Map.insert field rename shortNames
200{-# NOINLINE reservedNames #-}
201reservedNames :: Set.Set N.Name
203 Set.union jsReservedWords elmReservedWords
206jsReservedWords :: Set.Set N.Name
210 , "NaN", "int", "for", "new", "try", "var", "let"
211 , "null", "true", "eval", "byte", "char", "goto", "long", "case", "else", "this", "void", "with", "enum"
212 , "false", "final", "float", "short", "break", "catch", "throw", "while", "class", "const", "super", "yield"
213 , "double", "native", "throws", "delete", "return", "switch", "typeof", "export", "import", "public", "static"
214 , "boolean", "default", "finally", "extends", "package", "private"
215 , "Infinity", "abstract", "volatile", "function", "continue", "debugger", "function"
216 , "undefined", "arguments", "transient", "interface", "protected"
217 , "instanceof", "implements"
222elmReservedWords :: Set.Set N.Name
225 [ "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
226 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
234intToAscii :: Int -> S.ShortByteString
236 if n < 53 then -- skip $ as a standalone name
240 intToAsciiHelp 2 (numStartBytes * numInnerBytes) allBadFields (n - 53)
243intToAsciiHelp :: Int -> Int -> [BadFields] -> Int -> S.ShortByteString
244intToAsciiHelp width blockSize badFields n =
247 if n < blockSize then
248 unsafeIntToAscii width [] n
250 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) [] (n - blockSize)
252 BadFields renamings : biggerBadFields ->
253 let availableSize = blockSize - Map.size renamings in
254 if n < availableSize then
255 let name = unsafeIntToAscii width [] n in
256 Map.findWithDefault name name renamings
258 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) biggerBadFields (n - availableSize)
262-- UNSAFE INT TO ASCII
265unsafeIntToAscii :: Int -> [Word8] -> Int -> S.ShortByteString
266unsafeIntToAscii width bytes n =
268 S.pack (toByte n : bytes)
271 (quotient, remainder) =
272 quotRem n numInnerBytes
274 unsafeIntToAscii (width - 1) (toByte remainder : bytes) quotient
291toByte :: Int -> Word8
293 | n < 26 = fromIntegral (97 + n ) {- lower -}
294 | n < 52 = fromIntegral (65 + n - 26) {- upper -}
295 | n == 52 = 95 {- _ -}
296 | n == 53 = 36 {- $ -}
297 | n < 64 = fromIntegral (48 + n - 54) {- digit -}
298 | True = error $ "cannot convert int " ++ show n ++ " to ASCII"
306 BadFields { _renamings :: Renamings }
310 Map.Map S.ShortByteString S.ShortByteString
313allBadFields :: [BadFields]
317 Map.alter (Just . addRenaming keyword) (N.length keyword) dict
319 Map.elems $ Set.foldr add Map.empty jsReservedWords
322addRenaming :: N.Name -> Maybe BadFields -> BadFields
323addRenaming keyword maybeBadFields =
325 width = N.length keyword
326 maxName = numStartBytes * numInnerBytes ^ (width - 1) - 1
328 case maybeBadFields of
330 BadFields $ Map.singleton (N.toShort keyword) (unsafeIntToAscii width [] maxName)
332 Just (BadFields renamings) ->
333 BadFields $ Map.insert (N.toShort keyword) (unsafeIntToAscii width [] (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