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