on 1fa2684 help sign in
elk/src/Generate/JavaScript/Variable.hs
118 lines 3.3 kB history raw
1module Generate.JavaScript.Variable (fresh, canonical, define, safe) where
3import qualified Control.Monad.State as State
4import qualified Data.List as List
5import qualified Data.Set as Set
6import qualified Language.ECMAScript3.Syntax as JS
8import qualified AST.Helpers as Help
9import qualified AST.Module.Name as ModuleName
10import qualified AST.Variable as Var
11import qualified Elm.Package as Pkg
12import qualified Generate.JavaScript.Helpers as JS
15-- FRESH NAMES
17fresh :: State.State Int String
18fresh =
19 do n <- State.get
20 State.modify (+1)
21 return ("_v" ++ show n)
24-- DEF NAMES
26define :: Maybe ModuleName.Canonical -> String -> JS.Expression () -> JS.Statement ()
27define maybeHome name body =
28 let
29 varDecl safeName =
30 JS.VarDeclStmt () [ JS.VarDecl () (JS.Id () safeName) (Just body) ]
31 in
32 case maybeHome of
33 Nothing ->
34 varDecl (safe name)
36 Just home ->
37 if Help.isOp name then
38 let
39 root =
40 JS.VarRef () (JS.Id () (canonicalPrefix home "_op"))
42 lvalue =
43 JS.LBracket () root (JS.StringLit () name)
44 in
45 JS.ExprStmt () (JS.AssignExpr () JS.OpAssign lvalue body)
47 else
48 varDecl (canonicalPrefix home (safe name))
51-- INSTANTIATE VARIABLES
53canonical :: Var.Canonical -> JS.Expression ()
54canonical (Var.Canonical home name) =
55 if Help.isOp name then
56 JS.BracketRef () (JS.ref (addRoot home "_op")) (JS.string name)
58 else
59 JS.ref (addRoot home (safe name))
62addRoot :: Var.Home -> String -> String
63addRoot home name =
64 case home of
65 Var.Local ->
66 name
68 Var.TopLevel moduleName ->
69 canonicalPrefix moduleName name
71 Var.BuiltIn ->
72 name
74 Var.Module moduleName ->
75 canonicalPrefix moduleName name
78canonicalPrefix :: ModuleName.Canonical -> String -> String
79canonicalPrefix (ModuleName.Canonical (Pkg.Name user project) moduleName) name =
80 map (swap '-' '_') user
81 ++ '$' : map (swap '-' '_') project
82 ++ '$' : List.intercalate "$" moduleName
83 ++ '$' : safe name
86swap :: Char -> Char -> Char -> Char
87swap from to c =
88 if c == from then to else c
91-- SAFE NAMES
93safe :: String -> String
94safe name =
95 let saferName =
96 if Set.member name jsReserveds then '$' : name else name
97 in
98 map (swap '\'' '$') saferName
101jsReserveds :: Set.Set String
102jsReserveds =
103 Set.fromList
104 -- JS reserved words
105 [ "null", "undefined", "Nan", "Infinity", "true", "false", "eval"
106 , "arguments", "int", "byte", "char", "goto", "long", "final", "float"
107 , "short", "double", "native", "throws", "boolean", "abstract", "volatile"
108 , "transient", "synchronized", "function", "break", "case", "catch"
109 , "continue", "debugger", "default", "delete", "do", "else", "finally"
110 , "for", "function", "if", "in", "instanceof", "new", "return", "switch"
111 , "this", "throw", "try", "typeof", "var", "void", "while", "with", "class"
112 , "const", "enum", "export", "extends", "import", "super", "implements"
113 , "interface", "let", "package", "private", "protected", "public"
114 , "static", "yield"
115 -- reserved by the Elm runtime system
116 , "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
117 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
118 ]