@@ -1,4 +1,4 @@
1−module Generate.JavaScript where
1+module Generate.JavaScript (generate) where
3import Control.Arrow (first,(***))
3import Control.Arrow (first,(***))
4import Control.Applicative ((<$>),(<*>))
4import Control.Applicative ((<$>),(<*>))
@@ -9,30 +9,27 @@ import qualified Data.Set as Set
10import qualified Generate.Cases as Case
10import qualified Generate.Cases as Case
11import qualified Generate.Markdown as MD
11import qualified Generate.Markdown as MD
12+import qualified SourceSyntax.Helpers as Help
13+import SourceSyntax.Literal
12−import SourceSyntax.Everything
14+import SourceSyntax.Pattern
13import SourceSyntax.Location
15import SourceSyntax.Location
16+import SourceSyntax.Expression
17+import SourceSyntax.Module
14import qualified Transform.SortDefinitions as SD
18import qualified Transform.SortDefinitions as SD
15import Language.ECMAScript3.Syntax
19import Language.ECMAScript3.Syntax
16import Language.ECMAScript3.PrettyPrint
20import Language.ECMAScript3.PrettyPrint
17−import Parse.Helpers (jsReserveds)
21+import qualified Transform.SafeNames as MakeSafe
19−makeSafe :: String -> String
20−makeSafe = List.intercalate "." . map dereserve . split . deprime
22− deprime = map (\c -> if c == '\'' then '$' else c)
23− dereserve x = case Set.member x jsReserveds of
23+split :: String -> [String]
27split = go []
24split = go []
29 go vars str =
26 go vars str =
30 case break (=='.') str of
27 case break (=='.') str of
31− (x,'.':rest) | isOp x -> vars ++ [x ++ '.' : rest]
28+ (x,'.':rest) | Help.isOp x -> vars ++ [x ++ '.' : rest]
32 | otherwise -> go (vars ++ [x]) rest
29 | otherwise -> go (vars ++ [x]) rest
33 (x,[]) -> vars ++ [x]
30 (x,[]) -> vars ++ [x]
35−var name = Id () (makeSafe name)
32+var name = Id () name
36ref name = VarRef () (var name)
33ref name = VarRef () (var name)
37prop name = PropId () (var name)
34prop name = PropId () (var name)
38f <| x = CallExpr () f [x]
35f <| x = CallExpr () f [x]
@@ -44,11 +41,12 @@ string = StringLit ()
44dotSep (x:xs) = foldl (DotRef ()) (ref x) (map var xs)
41dotSep (x:xs) = foldl (DotRef ()) (ref x) (map var xs)
45obj = dotSep . split
42obj = dotSep . split
44+varDecl :: String -> Expression () -> VarDecl ()
47varDecl x expr =
45varDecl x expr =
48 VarDecl () (var x) (Just expr)
46 VarDecl () (var x) (Just expr)
50include alias moduleName =
48include alias moduleName =
51− varDecl alias (obj (moduleName ++ ".make") <| ref "elm")
49+ varDecl alias (obj (moduleName ++ ".make") <| ref "_elm")
53internalImports name =
51internalImports name =
54 VarDeclStmt ()
52 VarDeclStmt ()
@@ -60,6 +58,7 @@ internalImports name =
60 , varDecl "$moduleName" (string name)
58 , varDecl "$moduleName" (string name)
61+literal :: Literal -> Expression ()
63literal lit =
62literal lit =
64 case lit of
63 case lit of
65 Chr c -> obj "_N.chr" <| string [c]
64 Chr c -> obj "_N.chr" <| string [c]
@@ -114,18 +113,17 @@ expression (L span expr) =
114 Binop op e1 e2 -> binop span op e1 e2
113 Binop op e1 e2 -> binop span op e1 e2
116 Lambda p e@(L s _) ->
115 Lambda p e@(L s _) ->
116+ do (args, body) <- foldM depattern ([], innerBody) (reverse patterns)
117− do body' <- expression body
117+ body' <- expression body
118 return $ case length args < 2 || length args > 9 of
118 return $ case length args < 2 || length args > 9 of
119 True -> foldr (==>) body' (map (:[]) args)
119 True -> foldr (==>) body' (map (:[]) args)
120 False -> ref ("F" ++ show (length args)) <| (args ==> body')
120 False -> ref ("F" ++ show (length args)) <| (args ==> body')
122− (args, body) = foldr depattern ([], innerBody) (zip patterns [0..])
122+ depattern (args, body) pattern =
124− depattern (pattern,n) (args, body) =
125 case pattern of
123 case pattern of
126− PVar x -> (args ++ [x], body)
124+ PVar x -> return (args ++ [x], body)
127− _ -> let arg = "arg" ++ show n
125+ _ -> do arg <- Case.newVar
128− in (args ++ [arg], L s (Case (L s (Var arg)) [(pattern, body)]))
126+ return (args ++ [arg], L s (Case (L s (Var arg)) [(pattern, body)]))
130 (patterns, innerBody) = collect [p] e
128 (patterns, innerBody) = collect [p] e
@@ -156,14 +154,15 @@ expression (L span expr) =
156 return $ function [] (stmts ++ [ ReturnStmt () (Just exp) ]) `call` []
154 return $ function [] (stmts ++ [ ReturnStmt () (Just exp) ]) `call` []
158 MultiIf branches ->
156 MultiIf branches ->
159− do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
157+ do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
160− return $ case last branches of
158+ return $ case last branches of
161− (L _ (Var "Basics.otherwise"), e) -> ifs (init branches') (snd (last branches'))
159+ (L _ (Var "Basics.otherwise"), _) -> safeIfs branches'
162− _ -> ifs branches'
160+ (L _ (Literal (Boolean True)), _) -> safeIfs branches'
163− (obj "_E.If" `call` [ ref "$moduleName", string (show span) ])
161+ _ -> ifs branches' (obj "_E.If" `call` [ ref "$moduleName", string (show span) ])
163+ safeIfs branches = ifs (init branches) (snd (last branches))
165− ifs branches finally = foldr iff finally branches
164+ ifs branches finally = foldr iff finally branches
166− iff (if', then') else' = CondExpr () if' then' else'
165+ iff (if', then') else' = CondExpr () if' then' else'
168 Case e cases ->
167 Case e cases ->
169 do (tempVar,initialMatch) <- Case.toMatch cases
168 do (tempVar,initialMatch) <- Case.toMatch cases
@@ -183,11 +182,15 @@ expression (L span expr) =
183 do es' <- mapM expression es
182 do es' <- mapM expression es
184 return $ ObjectLit () (ctor : fields es')
183 return $ ObjectLit () (ctor : fields es')
186− ctor = (prop "ctor", string (makeSafe name))
185+ ctor = (prop "ctor", string name)
187 fields = zipWith (\n e -> (prop ("_" ++ show n), e)) [0..]
186 fields = zipWith (\n e -> (prop ("_" ++ show n), e)) [0..]
189− Markdown md _ -> return $ obj "Text.text" <| string (pad ++ MD.toHtml md ++ pad)
188+ Markdown uid doc es ->
189+ do es' <- mapM expression es
190+ return $ obj "Text.markdown" `call` (string md : string uid : es')
190− where pad = "<div style=\"height:0;width:0;\"> </div>"
192+ pad = "<div style=\"height:0;width:0;\"> </div>"
193+ md = pad ++ MD.toHtml doc ++ pad
192definition :: Def () () -> State Int [Statement ()]
195definition :: Def () () -> State Int [Statement ()]
193definition def =
196definition def =
@@ -199,7 +202,7 @@ definition def =
199 let assign x = varDecl x expr'
202 let assign x = varDecl x expr'
200 case pattern of
203 case pattern of
202− | isOp x ->
205+ | Help.isOp x ->
203 let op = LBracket () (ref "_op") (string x) in
206 let op = LBracket () (ref "_op") (string x) in
204 return [ ExprStmt () $ AssignExpr () OpAssign op expr' ]
207 return [ ExprStmt () $ AssignExpr () OpAssign op expr' ]
205 | otherwise ->
208 | otherwise ->
@@ -222,11 +225,11 @@ definition def =
223 decl x n = varDecl x (dotSep ["$","_" ++ show n])
226 decl x n = varDecl x (dotSep ["$","_" ++ show n])
224 setup vars
227 setup vars
225− | isTuple name = assign "$" : vars
228+ | Help.isTuple name = assign "$" : vars
226− | otherwise = safeAssign : vars
229+ | otherwise = assign "$raw" : safeAssign : vars
228− safeAssign = varDecl "$" (CondExpr () if' expr' exception)
231+ safeAssign = varDecl "$" (CondExpr () if' (obj "$raw") exception)
229− if' = InfixExpr () OpStrictEq (obj "$.ctor") (string name)
232+ if' = InfixExpr () OpStrictEq (obj "$raw.ctor") (string name)
230 exception = obj "_E.Case" `call` [ref "$moduleName", string (show span)]
233 exception = obj "_E.Case" `call` [ref "$moduleName", string (show span)]
@@ -284,14 +287,15 @@ clause span variable (Case.Clause value vars mtch) =
284 is -> drop (last is + 1) name
287 is -> drop (last is + 1) name
287−jsModule :: MetadataModule () () -> String
290+generate :: MetadataModule () () -> String
288−jsModule modul =
291+generate unsafeModule =
289 show . prettyPrint $ setup (Just "Elm") (names modul ++ ["make"]) ++
292 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) ]
295+ modul = MakeSafe.metadataModule unsafeModule
292− thisModule = dotSep ("elm" : names modul ++ ["values"])
296+ thisModule = dotSep ("_elm" : names modul ++ ["values"])
293 programStmts =
297 programStmts =
294− concat [ setup (Just "elm") (names modul ++ ["values"])
298+ concat [ setup (Just "_elm") (names modul ++ ["values"])
295 , [ IfSingleStmt () thisModule (ReturnStmt () (Just thisModule)) ]
299 , [ IfSingleStmt () thisModule (ReturnStmt () (Just thisModule)) ]
296 , [ internalImports (List.intercalate "." (names modul)) ]
300 , [ internalImports (List.intercalate "." (names modul)) ]
297 , concatMap jsImport (imports modul)
301 , concatMap jsImport (imports modul)
@@ -303,9 +307,9 @@ jsModule modul =
303 , [ ReturnStmt () (Just thisModule) ]
307 , [ ReturnStmt () (Just thisModule) ]
306− jsExports = assign ("elm" : names modul ++ ["values"]) (ObjectLit () exs)
310+ jsExports = assign ("_elm" : names modul ++ ["values"]) (ObjectLit () exs)
308− exs = map entry . filter (not . isOp) $ "_op" : exports modul
312+ exs = map entry . filter (not . Help.isOp) $ "_op" : exports modul
309 entry x = (PropId () (var x), ref x)
313 entry x = (PropId () (var x), ref x)
311 assign path expr =
315 assign path expr =
@@ -317,7 +321,7 @@ jsModule modul =
317 jsImport (modul,_) = setup Nothing path ++ [ include ]
321 jsImport (modul,_) = setup Nothing path ++ [ include ]
319 path = split modul
323 path = split modul
320− include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "elm"
324+ include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "_elm"
322 setup namespace path = map create paths
326 setup namespace path = map create paths
@@ -326,15 +330,15 @@ jsModule modul =
326 Nothing -> tail . init $ List.inits path
330 Nothing -> tail . init $ List.inits path
327 Just nmspc -> drop 2 . init . List.inits $ nmspc : path
331 Just nmspc -> drop 2 . init . List.inits $ nmspc : path
329− addId js = InfixExpr () OpAdd (string (js++"_")) (obj "elm.id")
333+ addId js = InfixExpr () OpAdd (string (js++"_")) (obj "_elm.id")
331 importEvent (js,base,elm,_) =
335 importEvent (js,base,elm,_) =
332 [ VarDeclStmt () [ varDecl elm $ obj "Signal.constant" <| evalState (expression base) 0 ]
336 [ VarDeclStmt () [ varDecl elm $ obj "Signal.constant" <| evalState (expression base) 0 ]
333 , ExprStmt () $
337 , ExprStmt () $
334 obj "document.addEventListener" `call`
338 obj "document.addEventListener" `call`
335 [ addId js
339 [ addId js
336− , function ["e"]
340+ , function ["_e"]
337− [ ExprStmt () $ obj "elm.notify" `call` [dotSep [elm,"id"], obj "e.value"] ]
341+ [ ExprStmt () $ obj "_elm.notify" `call` [dotSep [elm,"id"], obj "_e.value"] ]
@@ -342,13 +346,13 @@ jsModule modul =
342 ExprStmt () $
346 ExprStmt () $
343 ref "A2" `call`
347 ref "A2" `call`
344 [ obj "Signal.lift"
348 [ obj "Signal.lift"
345− , function ["v"]
349+ , function ["_v"]
346− [ VarDeclStmt () [varDecl "e" $ obj "document.createEvent" <| string "Event"]
350+ [ VarDeclStmt () [varDecl "_e" $ obj "document.createEvent" <| string "Event"]
347 , ExprStmt () $
351 , ExprStmt () $
348− obj "e.initEvent" `call` [ addId js, BoolLit () True, BoolLit () True ]
352+ obj "_e.initEvent" `call` [ addId js, BoolLit () True, BoolLit () True ]
349− , ExprStmt () $ AssignExpr () OpAssign (LDot () (ref "e") "value") (ref "v")
353+ , ExprStmt () $ AssignExpr () OpAssign (LDot () (ref "_e") "value") (ref "_v")
350− , ExprStmt () $ obj "document.dispatchEvent" <| ref "e"
354+ , ExprStmt () $ obj "document.dispatchEvent" <| ref "_e"
351− , ReturnStmt () (Just $ ref "v")
355+ , ReturnStmt () (Just $ ref "_v")
353 , ref elm ]
357 , ref elm ]
@@ -381,7 +385,7 @@ binop span op e1 e2 =
381 js1 = expression e1
385 js1 = expression e1
382 js2 = expression e2
386 js2 = expression e2
384− func | isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
388+ func | Help.isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
385 | otherwise = dotSep parts
389 | otherwise = dotSep parts
387 parts = split op
391 parts = split op