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 Data.Word (Word8)
28import qualified Data.Index as Index
29import qualified Elm.ModuleName as ModuleName
30import qualified Elm.Package as Pkg
38 Name { toBuilder :: B.Builder }
45fromIndex :: Index.ZeroBased -> Name
47 fromInt (Index.toMachine index)
52 Name (Name.toBuilder (intToAscii n))
55fromLocal :: Name.Name -> Name
57 if Set.member name reservedNames then
58 Name ("_" <> Name.toBuilder name)
60 Name (Name.toBuilder name)
63fromGlobal :: ModuleName.Canonical -> Name.Name -> Name
64fromGlobal (ModuleName.Canonical (Pkg.Name author project) home) name =
65 Name $ Name.toEscapedBuilder 0x2D {- - -} 0x5F {- _ -} author
66 <> "$" <> Name.toEscapedBuilder 0x2D {- - -} 0x5F {- _ -} project
67 <> "$" <> Name.toEscapedBuilder 0x2E {- . -} 0x24 {- $ -} home
68 <> "$" <> Name.toBuilder name
71fromCycle :: ModuleName.Canonical -> Name.Name -> Name
72fromCycle (ModuleName.Canonical (Pkg.Name author project) home) name =
73 Name $ Name.toEscapedBuilder 0x2D {- - -} 0x5F {- _ -} author
74 <> "$" <> Name.toEscapedBuilder 0x2D {- - -} 0x5F {- _ -} project
75 <> "$" <> Name.toEscapedBuilder 0x2E {- . -} 0x24 {- $ -} home
76 <> "$cyclic$" <> Name.toBuilder name
79fromKernel :: Name.Name -> Name.Name -> Name
81 Name ("_" <> Name.toBuilder home <> "_" <> Name.toBuilder name)
90 Name ("F" <> B.intDec n)
95 Name ("A" <> B.intDec n)
98makeLabel :: Name.Name -> Int -> Name
100 Name (Name.toBuilder name <> "$" <> B.intDec index)
103makeTemp :: Name.Name -> Name
105 Name ("$temp$" <> Name.toBuilder name)
110 Name (Name.toBuilder Name.dollar)
117{-# NOINLINE reservedNames #-}
118reservedNames :: Set.Set Name.Name
120 Set.union jsReservedWords elmReservedWords
123jsReservedWords :: Set.Set Name.Name
127 , "NaN", "int", "for", "new", "try", "var", "let"
128 , "null", "true", "eval", "byte", "char", "goto", "long", "case", "else", "this", "void", "with", "enum"
129 , "false", "final", "float", "short", "break", "catch", "throw", "while", "class", "const", "super", "yield"
130 , "double", "native", "throws", "delete", "return", "switch", "typeof", "export", "import", "public", "static"
131 , "boolean", "default", "finally", "extends", "package", "private"
132 , "Infinity", "abstract", "volatile", "function", "continue", "debugger", "function"
133 , "undefined", "arguments", "transient", "interface", "protected"
134 , "instanceof", "implements"
139elmReservedWords :: Set.Set Name.Name
142 [ "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
143 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
151intToAscii :: Int -> Name.Name
153 if n < 53 then -- skip $ as a standalone name
154 Name.fromWords [toByte n]
157 intToAsciiHelp 2 (numStartBytes * numInnerBytes) allBadFields (n - 53)
160intToAsciiHelp :: Int -> Int -> [BadFields] -> Int -> Name.Name
161intToAsciiHelp width blockSize badFields n =
164 if n < blockSize then
165 unsafeIntToAscii width [] n
167 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) [] (n - blockSize)
169 BadFields renamings : biggerBadFields ->
170 let availableSize = blockSize - Map.size renamings in
171 if n < availableSize then
172 let name = unsafeIntToAscii width [] n in
173 Map.findWithDefault name name renamings
175 intToAsciiHelp (width + 1) (blockSize * numInnerBytes) biggerBadFields (n - availableSize)
179-- UNSAFE INT TO ASCII
182unsafeIntToAscii :: Int -> [Word8] -> Int -> Name.Name
183unsafeIntToAscii width bytes n =
185 Name.fromWords (toByte n : bytes)
188 (quotient, remainder) =
189 quotRem n numInnerBytes
191 unsafeIntToAscii (width - 1) (toByte remainder : bytes) quotient
208toByte :: Int -> Word8
210 | n < 26 = fromIntegral (97 + n ) {- lower -}
211 | n < 52 = fromIntegral (65 + n - 26) {- upper -}
212 | n == 52 = 95 {- _ -}
213 | n == 53 = 36 {- $ -}
214 | n < 64 = fromIntegral (48 + n - 54) {- digit -}
215 | True = error $ "cannot convert int " ++ show n ++ " to ASCII"
223 BadFields { _renamings :: Renamings }
227 Map.Map Name.Name Name.Name
230allBadFields :: [BadFields]
234 Map.alter (Just . addRenaming keyword) (Name.length keyword) dict
236 Map.elems $ Set.foldr add Map.empty jsReservedWords
239addRenaming :: Name.Name -> Maybe BadFields -> BadFields
240addRenaming keyword maybeBadFields =
242 width = Name.length keyword
243 maxName = numStartBytes * numInnerBytes ^ (width - 1) - 1
245 case maybeBadFields of
247 BadFields $ Map.singleton keyword (unsafeIntToAscii width [] maxName)
249 Just (BadFields renamings) ->
250 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