1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript.Name
21import qualified Data.ByteString.Builder as B
22import Data.Monoid ((<>))
23import qualified Data.Map as Map
24import qualified Data.Name as Name
25import qualified Data.Set as Set
26import qualified Data.Utf8 as Utf8
27import Data.Word (Word8)
29import qualified Data.Index as Index
30import qualified Elm.ModuleName as ModuleName
31import qualified Elm.Package as Pkg
39 Name { toBuilder :: B.Builder }
46fromIndex :: Index.ZeroBased -> Name
48 fromInt (Index.toMachine index)
53 Name (Name.toBuilder (intToAscii n))
56fromLocal :: Name.Name -> Name
58 if Set.member name reservedNames then
59 Name ("_" <> Name.toBuilder name)
61 Name (Name.toBuilder name)
64fromGlobal :: ModuleName.Canonical -> Name.Name -> Name
66 Name $ homeToBuilder home <> usd <> Name.toBuilder name
69fromCycle :: ModuleName.Canonical -> Name.Name -> Name
71 Name $ homeToBuilder home <> "$cyclic$" <> Name.toBuilder name
74fromKernel :: Name.Name -> Name.Name -> Name
76 Name ("_" <> Name.toBuilder home <> "_" <> Name.toBuilder name)
79{-# INLINE homeToBuilder #-}
80homeToBuilder :: ModuleName.Canonical -> B.Builder
81homeToBuilder (ModuleName.Canonical (Pkg.Name author project) home) =
83 Utf8.toEscapedBuilder 0x2D {- - -} 0x5F {- _ -} author
85 Utf8.toEscapedBuilder 0x2D {- - -} 0x5F {- _ -} project
87 Utf8.toEscapedBuilder 0x2E {- . -} 0x24 {- $ -} home
96 Name ("F" <> B.intDec n)
101 Name ("A" <> B.intDec n)
104makeLabel :: Name.Name -> Int -> Name
105makeLabel name index =
106 Name (Name.toBuilder name <> usd <> B.intDec index)
109makeTemp :: Name.Name -> Name
111 Name ("$temp$" <> Name.toBuilder name)
121 Name.toBuilder Name.dollar
128{-# NOINLINE reservedNames #-}
129reservedNames :: Set.Set Name.Name
131 Set.union jsReservedWords elmReservedWords
134jsReservedWords :: Set.Set Name.Name
138 , "NaN", "int", "for", "new", "try", "var", "let"
139 , "null", "true", "eval", "byte", "char", "goto", "long", "case", "else", "this", "void", "with", "enum"
140 , "false", "final", "float", "short", "break", "catch", "throw", "while", "class", "const", "super", "yield"
141 , "double", "native", "throws", "delete", "return", "switch", "typeof", "export", "import", "public", "static"
142 , "boolean", "default", "finally", "extends", "package", "private"
143 , "Infinity", "abstract", "volatile", "function", "continue", "debugger", "function"
144 , "undefined", "arguments", "transient", "interface", "protected"
145 , "instanceof", "implements"
150elmReservedWords :: Set.Set Name.Name
153 [ "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
154 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
162intToAscii :: Int -> Name.Name
164 if n < 53 then -- skip $ as a standalone name
165 Name.fromWords [toByte n]
168 intToAsciiHelp 2 (numStartBytes * numInnerBytes) allBadFields (n - 53)
171intToAsciiHelp :: Int -> Int -> [BadFields] -> Int -> Name.Name
172intToAsciiHelp width blockSize badFields n =
175 if n < blockSize then
176 unsafeIntToAscii width [] n
178 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) [] (n - blockSize)
180 BadFields renamings : biggerBadFields ->
181 let availableSize = blockSize - Map.size renamings in
182 if n < availableSize then
183 let name = unsafeIntToAscii width [] n in
184 Map.findWithDefault name name renamings
186 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) biggerBadFields (n - availableSize)
190-- UNSAFE INT TO ASCII
193unsafeIntToAscii :: Int -> [Word8] -> Int -> Name.Name
194unsafeIntToAscii width bytes n =
196 Name.fromWords (toByte n : bytes)
199 (quotient, remainder) =
200 quotRem n numInnerBytes
202 unsafeIntToAscii (width - 1) (toByte remainder : bytes) quotient
219toByte :: Int -> Word8
221 | n < 26 = fromIntegral (97 + n ) {- lower -}
222 | n < 52 = fromIntegral (65 + n - 26) {- upper -}
223 | n == 52 = 95 {- _ -}
224 | n == 53 = 36 {- $ -}
225 | n < 64 = fromIntegral (48 + n - 54) {- digit -}
226 | True = error $ "cannot convert int " ++ show n ++ " to ASCII"
234 BadFields { _renamings :: Renamings }
238 Map.Map Name.Name Name.Name
241allBadFields :: [BadFields]
245 Map.alter (Just . addRenaming keyword) (Utf8.size keyword) dict
247 Map.elems $ Set.foldr add Map.empty jsReservedWords
250addRenaming :: Name.Name -> Maybe BadFields -> BadFields
251addRenaming keyword maybeBadFields =
253 width = Utf8.size keyword
254 maxName = numStartBytes * numInnerBytes ^ (width - 1) - 1
256 case maybeBadFields of
258 BadFields $ Map.singleton keyword (unsafeIntToAscii width [] maxName)
260 Just (BadFields renamings) ->
261 BadFields $ Map.insert 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