1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript.Name
26import qualified Data.ByteString.Builder as B
27import qualified Data.ByteString.Short as S
28import qualified Data.List as List
29import Data.Monoid ((<>))
31import qualified Data.Map as Map
32import qualified Data.Set as Set
33import qualified Data.Text as Text
34import qualified Data.Text.Encoding as Text
35import Data.Word (Word8)
37import qualified AST.Module.Name as ModuleName
38import qualified Data.Index as Index
39import qualified Elm.Name as N
40import qualified Elm.Package as Pkg
48 Name { toBuilder :: B.Builder }
57 | Prod Target ShortFieldNames
60data Target = Client | Server
67isServer :: Mode -> Bool
70 Debug target -> isServerHelp target
71 Prod target _ -> isServerHelp target
74isServerHelp :: Target -> Bool
76 case target of { Client -> False ; Server -> True }
83fromIndex :: Index.ZeroBased -> Name
85 fromInt (Index.toMachine index)
90 Name (B.shortByteString (intToAscii n))
93fromLocal :: N.Name -> Name
95 if Set.member name reservedNames then
96 Name ("_" <> N.toBuilder name)
98 Name (N.toBuilder name)
101fromGlobal :: ModuleName.Canonical -> N.Name -> Name
102fromGlobal (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.toDotlessBuilder home
107 <> "$" <> N.toBuilder name
110fromCycle :: ModuleName.Canonical -> N.Name -> Name
111fromCycle (ModuleName.Canonical (Pkg.Name user project) home) name =
113 Text.encodeUtf8Builder (Text.replace "-" "_" user)
114 <> "$" <> Text.encodeUtf8Builder (Text.replace "-" "_" project) -- TODO store this in a better way
115 <> "$" <> N.toDotlessBuilder home
116 <> "$cyclic$" <> N.toBuilder name
119fromKernel :: N.Name -> N.Name -> Name
120fromKernel home name =
121 Name ("_" <> N.toBuilder home <> "_" <> N.toBuilder name)
124fromField :: Mode -> N.Name -> Name
128 Name (N.toBuilder name)
140 Name ("F" <> B.intDec n)
145 Name ("A" <> B.intDec n)
148makeLabel :: N.Name -> Int -> Name
149makeLabel name index =
150 Name (N.toBuilder name <> "$" <> B.intDec index)
153makeTemp :: N.Name -> Name
155 Name ("$temp$" <> N.toBuilder name)
160 Name (N.toBuilder N.dollar)
164-- SHORTEN FIELD NAMES
167shortenFieldNames :: Map.Map N.Name Int -> ShortFieldNames
168shortenFieldNames frequencies =
169 Map.foldr addToShortNames Map.empty $
170 Map.foldrWithKey addToBuckets Map.empty frequencies
173addToBuckets :: N.Name -> Int -> Map.Map Int [N.Name] -> Map.Map Int [N.Name]
174addToBuckets field frequency buckets =
175 -- TODO try using an IntMap for buckets
176 Map.insertWith (++) frequency [field] buckets
179addToShortNames :: [N.Name] -> ShortFieldNames -> ShortFieldNames
180addToShortNames fields shortNames =
181 List.foldl' addField shortNames fields
184addField :: ShortFieldNames -> N.Name -> ShortFieldNames
185addField shortNames field =
186 let rename = fromInt (Map.size shortNames) in
187 Map.insert field rename shortNames
194{-# NOINLINE reservedNames #-}
195reservedNames :: Set.Set N.Name
197 Set.union jsReservedWords elmReservedWords
200jsReservedWords :: Set.Set N.Name
204 , "NaN", "int", "for", "new", "try", "var", "let"
205 , "null", "true", "eval", "byte", "char", "goto", "long", "case", "else", "this", "void", "with", "enum"
206 , "false", "final", "float", "short", "break", "catch", "throw", "while", "class", "const", "super", "yield"
207 , "double", "native", "throws", "delete", "return", "switch", "typeof", "export", "import", "public", "static"
208 , "boolean", "default", "finally", "extends", "package", "private"
209 , "Infinity", "abstract", "volatile", "function", "continue", "debugger", "function"
210 , "undefined", "arguments", "transient", "interface", "protected"
211 , "instanceof", "implements"
216elmReservedWords :: Set.Set N.Name
219 [ "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
220 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
228intToAscii :: Int -> S.ShortByteString
230 if n < 53 then -- skip $ as a standalone name
234 intToAsciiHelp 2 (numStartBytes * numInnerBytes) allBadFields (n - 53)
237intToAsciiHelp :: Int -> Int -> [BadFields] -> Int -> S.ShortByteString
238intToAsciiHelp width blockSize badFields n =
241 if n < blockSize then
242 unsafeIntToAscii width [] n
244 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) [] (n - blockSize)
246 BadFields renamings : biggerBadFields ->
247 let availableSize = blockSize - Map.size renamings in
248 if n < availableSize then
249 let name = unsafeIntToAscii width [] n in
250 Map.findWithDefault name name renamings
252 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) biggerBadFields (n - availableSize)
256-- UNSAFE INT TO ASCII
259unsafeIntToAscii :: Int -> [Word8] -> Int -> S.ShortByteString
260unsafeIntToAscii width bytes n =
262 S.pack (toByte n : bytes)
265 (quotient, remainder) =
266 quotRem n numInnerBytes
268 unsafeIntToAscii (width - 1) (toByte remainder : bytes) quotient
285toByte :: Int -> Word8
287 | n < 26 = fromIntegral (97 + n ) {- lower -}
288 | n < 52 = fromIntegral (65 + n - 26) {- upper -}
289 | n == 52 = 95 {- _ -}
290 | n == 53 = 36 {- $ -}
291 | n < 64 = fromIntegral (48 + n - 54) {- digit -}
292 | True = error $ "cannot convert int " ++ show n ++ " to ASCII"
300 BadFields { _renamings :: Renamings }
304 Map.Map S.ShortByteString S.ShortByteString
307allBadFields :: [BadFields]
311 Map.alter (Just . addRenaming keyword) (N.length keyword) dict
313 Map.elems $ Set.foldr add Map.empty jsReservedWords
316addRenaming :: N.Name -> Maybe BadFields -> BadFields
317addRenaming keyword maybeBadFields =
319 width = N.length keyword
320 maxName = numStartBytes * numInnerBytes ^ (width - 1) - 1
322 case maybeBadFields of
324 BadFields $ Map.singleton (N.toShort keyword) (unsafeIntToAscii width [] maxName)
326 Just (BadFields renamings) ->
327 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