@@ -1,4 +1,4 @@
1−module Generate.JavaScript where
1+module Generate.JavaScript (generate) where
22
33import Control.Arrow (first,(***))
44import Control.Applicative ((<$>),(<*>))
@@ -9,30 +9,27 @@ import qualified Data.Set as Set
99
1010import qualified Generate.Cases as Case
1111import qualified Generate.Markdown as MD
12−import SourceSyntax.Everything
12+import qualified SourceSyntax.Helpers as Help
13+import SourceSyntax.Literal
14+import SourceSyntax.Pattern
1315import SourceSyntax.Location
16+import SourceSyntax.Expression
17+import SourceSyntax.Module
1418import qualified Transform.SortDefinitions as SD
1519import Language.ECMAScript3.Syntax
1620import Language.ECMAScript3.PrettyPrint
17−import Parse.Helpers (jsReserveds)
18−
19−makeSafe :: String -> String
20−makeSafe = List.intercalate "." . map dereserve . split . deprime
21− where
22− deprime = map (\c -> if c == '\'' then '$' else c)
23− dereserve x = case Set.member x jsReserveds of
24− False -> x
25− True -> "$" ++ x
21+import qualified Transform.SafeNames as MakeSafe
2622
23+split :: String -> [String]
2724split = go []
2825 where
2926 go vars str =
3027 case break (=='.') str of
31− (x,'.':rest) | isOp x -> vars ++ [x ++ '.' : rest]
28+ (x,'.':rest) | Help.isOp x -> vars ++ [x ++ '.' : rest]
3229 | otherwise -> go (vars ++ [x]) rest
3330 (x,[]) -> vars ++ [x]
3431
35−var name = Id () (makeSafe name)
32+var name = Id () name
3633ref name = VarRef () (var name)
3734prop name = PropId () (var name)
3835f <| x = CallExpr () f [x]
@@ -44,11 +41,12 @@ string = StringLit ()
4441dotSep (x:xs) = foldl (DotRef ()) (ref x) (map var xs)
4542obj = dotSep . split
4643
44+varDecl :: String -> Expression () -> VarDecl ()
4745varDecl x expr =
4846 VarDecl () (var x) (Just expr)
4947
5048include alias moduleName =
51− varDecl alias (obj (moduleName ++ ".make") <| ref "elm")
49+ varDecl alias (obj (moduleName ++ ".make") <| ref "_elm")
5250
5351internalImports name =
5452 VarDeclStmt ()
@@ -60,6 +58,7 @@ internalImports name =
6058 , varDecl "$moduleName" (string name)
6159 ]
6260
61+literal :: Literal -> Expression ()
6362literal lit =
6463 case lit of
6564 Chr c -> obj "_N.chr" <| string [c]
@@ -114,18 +113,17 @@ expression (L span expr) =
114113 Binop op e1 e2 -> binop span op e1 e2
115114
116115 Lambda p e@(L s _) ->
117− do body' <- expression body
116+ do (args, body) <- foldM depattern ([], innerBody) (reverse patterns)
117+ body' <- expression body
118118 return $ case length args < 2 || length args > 9 of
119119 True -> foldr (==>) body' (map (:[]) args)
120120 False -> ref ("F" ++ show (length args)) <| (args ==> body')
121121 where
122− (args, body) = foldr depattern ([], innerBody) (zip patterns [0..])
123−
124− depattern (pattern,n) (args, body) =
122+ depattern (args, body) pattern =
125123 case pattern of
126− PVar x -> (args ++ [x], body)
127− _ -> let arg = "arg" ++ show n
128− in (args ++ [arg], L s (Case (L s (Var arg)) [(pattern, body)]))
124+ PVar x -> return (args ++ [x], body)
125+ _ -> do arg <- Case.newVar
126+ return (args ++ [arg], L s (Case (L s (Var arg)) [(pattern, body)]))
129127
130128 (patterns, innerBody) = collect [p] e
131129
@@ -156,14 +154,15 @@ expression (L span expr) =
156154 return $ function [] (stmts ++ [ ReturnStmt () (Just exp) ]) `call` []
157155
158156 MultiIf branches ->
159− do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
160− return $ case last branches of
161− (L _ (Var "Basics.otherwise"), e) -> ifs (init branches') (snd (last branches'))
162− _ -> ifs branches'
163− (obj "_E.If" `call` [ ref "$moduleName", string (show span) ])
164− where
165− ifs branches finally = foldr iff finally branches
166− iff (if', then') else' = CondExpr () if' then' else'
157+ do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
158+ return $ case last branches of
159+ (L _ (Var "Basics.otherwise"), _) -> safeIfs branches'
160+ (L _ (Literal (Boolean True)), _) -> safeIfs branches'
161+ _ -> ifs branches' (obj "_E.If" `call` [ ref "$moduleName", string (show span) ])
162+ where
163+ safeIfs branches = ifs (init branches) (snd (last branches))
164+ ifs branches finally = foldr iff finally branches
165+ iff (if', then') else' = CondExpr () if' then' else'
167166
168167 Case e cases ->
169168 do (tempVar,initialMatch) <- Case.toMatch cases
@@ -183,11 +182,15 @@ expression (L span expr) =
183182 do es' <- mapM expression es
184183 return $ ObjectLit () (ctor : fields es')
185184 where
186− ctor = (prop "ctor", string (makeSafe name))
185+ ctor = (prop "ctor", string name)
187186 fields = zipWith (\n e -> (prop ("_" ++ show n), e)) [0..]
188187
189− Markdown md _ -> return $ obj "Text.text" <| string (pad ++ MD.toHtml md ++ pad)
190− where pad = "<div style=\"height:0;width:0;\"> </div>"
188+ Markdown uid doc es ->
189+ do es' <- mapM expression es
190+ return $ obj "Text.markdown" `call` (string md : string uid : es')
191+ where
192+ pad = "<div style=\"height:0;width:0;\"> </div>"
193+ md = pad ++ MD.toHtml doc ++ pad
191194
192195definition :: Def () () -> State Int [Statement ()]
193196definition def =
@@ -199,7 +202,7 @@ definition def =
199202 let assign x = varDecl x expr'
200203 case pattern of
201204 PVar x
202− | isOp x ->
205+ | Help.isOp x ->
203206 let op = LBracket () (ref "_op") (string x) in
204207 return [ ExprStmt () $ AssignExpr () OpAssign op expr' ]
205208 | otherwise ->
@@ -222,11 +225,11 @@ definition def =
222225
223226 decl x n = varDecl x (dotSep ["$","_" ++ show n])
224227 setup vars
225− | isTuple name = assign "$" : vars
226− | otherwise = safeAssign : vars
228+ | Help.isTuple name = assign "$" : vars
229+ | otherwise = assign "$raw" : safeAssign : vars
227230
228− safeAssign = varDecl "$" (CondExpr () if' expr' exception)
229− if' = InfixExpr () OpStrictEq (obj "$.ctor") (string name)
231+ safeAssign = varDecl "$" (CondExpr () if' (obj "$raw") exception)
232+ if' = InfixExpr () OpStrictEq (obj "$raw.ctor") (string name)
230233 exception = obj "_E.Case" `call` [ref "$moduleName", string (show span)]
231234
232235 _ ->
@@ -284,14 +287,15 @@ clause span variable (Case.Clause value vars mtch) =
284287 is -> drop (last is + 1) name
285288
286289
287−jsModule :: MetadataModule () () -> String
288−jsModule modul =
290+generate :: MetadataModule () () -> String
291+generate unsafeModule =
289292 show . prettyPrint $ setup (Just "Elm") (names modul ++ ["make"]) ++
290− [ assign ("Elm" : names modul ++ ["make"]) (function ["elm"] programStmts) ]
293+ [ assign ("Elm" : names modul ++ ["make"]) (function ["_elm"] programStmts) ]
291294 where
292− thisModule = dotSep ("elm" : names modul ++ ["values"])
295+ modul = MakeSafe.metadataModule unsafeModule
296+ thisModule = dotSep ("_elm" : names modul ++ ["values"])
293297 programStmts =
294− concat [ setup (Just "elm") (names modul ++ ["values"])
298+ concat [ setup (Just "_elm") (names modul ++ ["values"])
295299 , [ IfSingleStmt () thisModule (ReturnStmt () (Just thisModule)) ]
296300 , [ internalImports (List.intercalate "." (names modul)) ]
297301 , concatMap jsImport (imports modul)
@@ -303,9 +307,9 @@ jsModule modul =
303307 , [ ReturnStmt () (Just thisModule) ]
304308 ]
305309
306− jsExports = assign ("elm" : names modul ++ ["values"]) (ObjectLit () exs)
310+ jsExports = assign ("_elm" : names modul ++ ["values"]) (ObjectLit () exs)
307311 where
308− exs = map entry . filter (not . isOp) $ "_op" : exports modul
312+ exs = map entry . filter (not . Help.isOp) $ "_op" : exports modul
309313 entry x = (PropId () (var x), ref x)
310314
311315 assign path expr =
@@ -317,7 +321,7 @@ jsModule modul =
317321 jsImport (modul,_) = setup Nothing path ++ [ include ]
318322 where
319323 path = split modul
320− include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "elm"
324+ include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "_elm"
321325
322326 setup namespace path = map create paths
323327 where
@@ -326,15 +330,15 @@ jsModule modul =
326330 Nothing -> tail . init $ List.inits path
327331 Just nmspc -> drop 2 . init . List.inits $ nmspc : path
328332
329− addId js = InfixExpr () OpAdd (string (js++"_")) (obj "elm.id")
333+ addId js = InfixExpr () OpAdd (string (js++"_")) (obj "_elm.id")
330334
331335 importEvent (js,base,elm,_) =
332336 [ VarDeclStmt () [ varDecl elm $ obj "Signal.constant" <| evalState (expression base) 0 ]
333337 , ExprStmt () $
334338 obj "document.addEventListener" `call`
335339 [ addId js
336− , function ["e"]
337− [ ExprStmt () $ obj "elm.notify" `call` [dotSep [elm,"id"], obj "e.value"] ]
340+ , function ["_e"]
341+ [ ExprStmt () $ obj "_elm.notify" `call` [dotSep [elm,"id"], obj "_e.value"] ]
338342 ]
339343 ]
340344
@@ -342,13 +346,13 @@ jsModule modul =
342346 ExprStmt () $
343347 ref "A2" `call`
344348 [ obj "Signal.lift"
345− , function ["v"]
346− [ VarDeclStmt () [varDecl "e" $ obj "document.createEvent" <| string "Event"]
349+ , function ["_v"]
350+ [ VarDeclStmt () [varDecl "_e" $ obj "document.createEvent" <| string "Event"]
347351 , ExprStmt () $
348− obj "e.initEvent" `call` [ addId js, BoolLit () True, BoolLit () True ]
349− , ExprStmt () $ AssignExpr () OpAssign (LDot () (ref "e") "value") (ref "v")
350− , ExprStmt () $ obj "document.dispatchEvent" <| ref "e"
351− , ReturnStmt () (Just $ ref "v")
352+ obj "_e.initEvent" `call` [ addId js, BoolLit () True, BoolLit () True ]
353+ , ExprStmt () $ AssignExpr () OpAssign (LDot () (ref "_e") "value") (ref "_v")
354+ , ExprStmt () $ obj "document.dispatchEvent" <| ref "_e"
355+ , ReturnStmt () (Just $ ref "_v")
352356 ]
353357 , ref elm ]
354358
@@ -381,7 +385,7 @@ binop span op e1 e2 =
381385 js1 = expression e1
382386 js2 = expression e2
383387
384− func | isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
388+ func | Help.isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
385389 | otherwise = dotSep parts
386390 where
387391 parts = split op