on 219aff8 help sign in
elk/src/Generate/JavaScript/Variable.hs
147 lines 3.4 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript.Variable
4 ( fresh
5 , local
6 , global
7 , qualified
8 , coreNative
9 , staticProgram
10 , defineGlobal
11 , safe
12 )
13 where
15import qualified Control.Monad.State as State
16import Data.Monoid
17import qualified Data.Set as Set
18import qualified Data.Text as Text
19import Data.Text (Text)
21import qualified AST.Helpers as Help
22import qualified AST.Module.Name as ModuleName
23import qualified Elm.Package as Pkg
24import qualified Generate.JavaScript.Builder as JS
25import qualified Generate.JavaScript.Helpers as JS
29-- FRESH NAMES
32fresh :: State.State Int Text
33fresh =
34 do n <- State.get
35 State.modify (+1)
36 return (Text.pack ("_v" ++ show n))
40-- VARIABLES
43local :: Text -> JS.Expr
44local name =
45 JS.ref (safe name)
48global :: ModuleName.Canonical -> Text -> JS.Expr
49global home name =
50 if Help.isOp name then
51 JS.BracketRef (JS.ref (opsDict home)) (JS.String name)
52 else
53 JS.ref (qualified home name)
57-- MISC
60coreNative :: Text -> Text -> JS.Expr
61coreNative moduleName name =
62 global (ModuleName.inCore ("Native." <> moduleName)) name
65staticProgram :: JS.Expr
66staticProgram =
67 global (ModuleName.inVirtualDom "Native.VirtualDom") "staticProgram"
71-- DEFINE GLOBALS
74defineGlobal :: ModuleName.Canonical -> Text -> JS.Expr -> [JS.Stmt]
75defineGlobal home name body =
76 case Help.isOp name of
77 False ->
78 [ JS.VarDeclStmt [ JS.varDecl (qualified home name) body ]
79 ]
81 True ->
82 let
83 dict = opsDict home
84 lvalue = JS.LBracket (JS.ref dict) (JS.String name)
85 in
86 [ JS.VarDeclStmt [ JS.varDecl dict (JS.refOrObject dict) ]
87 , JS.ExprStmt (JS.Assign lvalue body)
88 ]
92-- GLOBAL NAMES
95qualified :: ModuleName.Canonical -> Text -> Text
96qualified home name =
97 moduleToText home <> "$" <> name
100opsDict :: ModuleName.Canonical -> Text
101opsDict home =
102 moduleToText home <> "_ops"
105moduleToText :: ModuleName.Canonical -> Text
106moduleToText (ModuleName.Canonical (Pkg.Name user project) moduleName) =
107 let
108 safeUser =
109 Text.replace "-" "_" user
111 safeProject =
112 Text.replace "-" "_" project
114 safeModuleName =
115 Text.replace "." "_" moduleName
116 in
117 "_" <> safeUser <> "$" <> safeProject <> "$" <> safeModuleName
121-- SAFE NAMES
124safe :: Text -> Text
125safe name =
126 if Set.member name jsReserveds then "_" <> name else name
129jsReserveds :: Set.Set Text
130jsReserveds =
131 Set.fromList
132 -- JS reserved words
133 [ "null", "undefined", "Nan", "Infinity", "true", "false", "eval"
134 , "arguments", "int", "byte", "char", "goto", "long", "final", "float"
135 , "short", "double", "native", "throws", "boolean", "abstract", "volatile"
136 , "transient", "synchronized", "function", "break", "case", "catch"
137 , "continue", "debugger", "default", "delete", "do", "else", "finally"
138 , "for", "function", "if", "in", "instanceof", "new", "return", "switch"
139 , "this", "throw", "try", "typeof", "var", "void", "while", "with", "class"
140 , "const", "enum", "export", "extends", "import", "super", "implements"
141 , "interface", "let", "package", "private", "protected", "public"
142 , "static", "yield"
143 -- reserved by the Elm runtime system
144 , "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
145 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
146 , "ctor"
147 ]