on 12fbd47 help sign in
elk/src/Generate/JavaScript/Variable.hs
148 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 , 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 AST.Variable as Var
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 :: Var.Global -> JS.Expr
50global (Var.Global 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
61coreNative :: Text -> Text -> JS.Expr
62coreNative moduleName name =
63 global (Var.Global (ModuleName.inCore ("Native." <> moduleName)) name)
66staticProgram :: JS.Expr
67staticProgram =
68 global (Var.Global (ModuleName.inVirtualDom "Native.VirtualDom") "staticProgram")
72-- DEFINE GLOBALS
75defineGlobal :: ModuleName.Canonical -> Text -> JS.Expr -> [JS.Stmt]
76defineGlobal home name body =
77 case Help.isOp name of
78 False ->
79 [ JS.VarDeclStmt [ JS.varDecl (qualified home name) body ]
80 ]
82 True ->
83 let
84 dict = opsDict home
85 lvalue = JS.LBracket (JS.ref dict) (JS.String name)
86 in
87 [ JS.VarDeclStmt [ JS.varDecl dict (JS.refOrObject dict) ]
88 , JS.ExprStmt (JS.Assign lvalue body)
89 ]
93-- GLOBAL NAMES
96qualified :: ModuleName.Canonical -> Text -> Text
97qualified home name =
98 moduleToText home <> "$" <> name
101opsDict :: ModuleName.Canonical -> Text
102opsDict home =
103 moduleToText home <> "_ops"
106moduleToText :: ModuleName.Canonical -> Text
107moduleToText (ModuleName.Canonical (Pkg.Name user project) moduleName) =
108 let
109 safeUser =
110 Text.replace "-" "_" user
112 safeProject =
113 Text.replace "-" "_" project
115 safeModuleName =
116 Text.replace "." "_" moduleName
117 in
118 "_" <> safeUser <> "$" <> safeProject <> "$" <> safeModuleName
122-- SAFE NAMES
125safe :: Text -> Text
126safe name =
127 if Set.member name jsReserveds then "_" <> name else name
130jsReserveds :: Set.Set Text
131jsReserveds =
132 Set.fromList
133 -- JS reserved words
134 [ "null", "undefined", "Nan", "Infinity", "true", "false", "eval"
135 , "arguments", "int", "byte", "char", "goto", "long", "final", "float"
136 , "short", "double", "native", "throws", "boolean", "abstract", "volatile"
137 , "transient", "synchronized", "function", "break", "case", "catch"
138 , "continue", "debugger", "default", "delete", "do", "else", "finally"
139 , "for", "function", "if", "in", "instanceof", "new", "return", "switch"
140 , "this", "throw", "try", "typeof", "var", "void", "while", "with", "class"
141 , "const", "enum", "export", "extends", "import", "super", "implements"
142 , "interface", "let", "package", "private", "protected", "public"
143 , "static", "yield"
144 -- reserved by the Elm runtime system
145 , "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
146 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
147 , "ctor"
148 ]