@@ -3,7 +3,7 @@ module Generate.JavaScript (showErr, jsModule) where
3import Control.Arrow (first,second)
3import Control.Arrow (first,second)
4import Control.Monad (liftM,(<=<),join,ap)
4import Control.Monad (liftM,(<=<),join,ap)
5import Data.Char (isAlpha,isDigit)
5import Data.Char (isAlpha,isDigit)
6−import Data.List (intercalate,inits,foldl')
6+import qualified Data.List as List
7import qualified Data.Map as Map
7import qualified Data.Map as Map
8import qualified Data.Set as Set
8import qualified Data.Set as Set
9import Data.Either (partitionEithers)
9import Data.Either (partitionEithers)
@@ -36,8 +36,10 @@ internalImports =
37parens s = "(" ++ s ++ ")"
37parens s = "(" ++ s ++ ")"
38brackets s = "{" ++ s ++ "}"
38brackets s = "{" ++ s ++ "}"
39+commaSep = List.intercalate ", "
40+dotSep = List.intercalate "."
39−jsObj = brackets . intercalate ", "
41+jsObj = brackets . commaSep
40−jsList ss = "["++ intercalate "," ss ++"]"
42+jsList ss = "["++ List.intercalate "," ss ++"]"
41jsFunc args body = "function(" ++ args ++ "){" ++ indent body ++ "}"
43jsFunc args body = "function(" ++ args ++ "){" ++ indent body ++ "}"
42assign x e = "\nvar " ++ x ++ " = " ++ e ++ ";"
44assign x e = "\nvar " ++ x ++ " = " ++ e ++ ";"
43ret e = "\nreturn "++ e ++";"
45ret e = "\nreturn "++ e ++";"
@@ -61,7 +63,7 @@ jsModule modul =
61 , globalAssign ("Elm." ++ modName)
63 , globalAssign ("Elm." ++ modName)
62 (jsFunc "elm" $ makeProgram body foreignImport) ]
64 (jsFunc "elm" $ makeProgram body foreignImport) ]
64− modName = intercalate "." (names modul)
66+ modName = dotSep (names modul)
65 makeProgram body foreignImport =
67 makeProgram body foreignImport =
66 concat [ "\nvar " ++ usefulFuncs ++ ";"
68 concat [ "\nvar " ++ usefulFuncs ++ ";"
67 , assign "_op" "{}"
69 , assign "_op" "{}"
@@ -75,8 +77,8 @@ jsModule modul =
75 , ret (assign' ("elm." ++ modName) "_")
77 , ret (assign' ("elm." ++ modName) "_")
77 setup names = concatMap (\n -> globalAssign n $ n ++ "||{}") .
79 setup names = concatMap (\n -> globalAssign n $ n ++ "||{}") .
78− map (intercalate ".") . drop 2 . inits $ init names
80+ map dotSep . drop 2 . List.inits $ init names
79− usefulFuncs = intercalate ", " (map (uncurry assign') internalImports)
81+ usefulFuncs = commaSep (map (uncurry assign') internalImports)
81 jsExport x =
83 jsExport x =
82 if isOp x then "\n_._op['" ++ x ++ "'] = _op['" ++ x ++ "'];"
84 if isOp x then "\n_._op['" ++ x ++ "'] = _op['" ++ x ++ "'];"
@@ -106,13 +108,13 @@ jsImport (modul, how) =
107 imprt v = assign' v ("_." ++ v)
109 imprt v = assign' v ("_." ++ v)
108 def x = imprt $ if isOp x then "_op['" ++ x ++ "']" else deprime x
110 def x = imprt $ if isOp x then "_op['" ++ x ++ "']" else deprime x
109− named = if null vs then "" else "\nvar " ++ intercalate ", " (map def vs) ++ ";"
111+ named = if null vs then "" else "\nvar " ++ commaSep (map def vs) ++ ";"
111 include = "\nvar _ = Elm." ++ modul ++ parens "elm" ++ ";" ++ setup modul
113 include = "\nvar _ = Elm." ++ modul ++ parens "elm" ++ ";" ++ setup modul
112 setup moduleName = " var " ++ concatMap (++";") (defs ++ [assign' moduleName "_"])
114 setup moduleName = " var " ++ concatMap (++";") (defs ++ [assign' moduleName "_"])
114 defs = map (\n -> assign' n (n ++ "||{}")) (subnames moduleName)
116 defs = map (\n -> assign' n (n ++ "||{}")) (subnames moduleName)
115− subnames = map (intercalate ".") . tail . inits . init . split
117+ subnames = map dotSep . tail . List.inits . init . split
116 split names = case go [] names of
118 split names = case go [] names of
117 (name, []) -> [name]
119 (name, []) -> [name]
118 (name, ns) -> name : split ns
120 (name, ns) -> name : split ns
@@ -163,12 +165,12 @@ access x e = e ++ "." ++ x
163makeRecord kvs = record `liftM` collect kvs
165makeRecord kvs = record `liftM` collect kvs
165 combine r (k,v) = Map.insertWith (++) k v r
167 combine r (k,v) = Map.insertWith (++) k v r
166− collect = liftM (foldl' combine Map.empty) . mapM prep
168+ collect = liftM (List.foldl' combine Map.empty) . mapM prep
167 prep (k, e) =
169 prep (k, e) =
168 do v <- toJS' e
170 do v <- toJS' e
169 return (k,[v])
171 return (k,[v])
170 fields fs =
172 fields fs =
171− brackets ("\n "++intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
173+ brackets ("\n "++List.intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
172 hidden = fields . map (second jsList) .
174 hidden = fields . map (second jsList) .
173 filter (not . null . snd) . Map.toList . Map.map tail
175 filter (not . null . snd) . Map.toList . Map.map tail
174 record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
176 record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
@@ -198,7 +200,7 @@ instance ToJS (Expr t v) where
198 Record fs -> makeRecord fs
200 Record fs -> makeRecord fs
199 Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
201 Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
201− Lambda p e -> liftM (jsFunc (intercalate ", " args) . ret) (toJS' body)
203+ Lambda p e -> liftM (jsFunc (commaSep args) . ret) (toJS' body)
203 (args, body) = foldr depattern ([], innerBody) (zip patterns [1..])
205 (args, body) = foldr depattern ([], innerBody) (zip patterns [1..])
@@ -239,7 +241,7 @@ jsApp e1 e2 =
239 as <- mapM toJS' args
241 as <- mapM toJS' args
240 return $ case as of
242 return $ case as of
241 [a] -> f ++ parens a
243 [a] -> f ++ parens a
242− _ -> "A" ++ show (length as) ++ parens (intercalate ", " (f:as))
244+ _ -> "A" ++ show (length as) ++ parens (commaSep (f:as))
244 (func, args) = go [e2] e1
246 (func, args) = go [e2] e1
245 go args e =
247 go args e =
@@ -315,6 +317,7 @@ jsCons e1 e2 = "_L.Cons(" ++ e1 ++ "," ++ e2 ++ ")"
315jsRange e1 e2 = "_L.range" ++ parens (e1 ++ "," ++ e2)
317jsRange e1 e2 = "_L.range" ++ parens (e1 ++ "," ++ e2)
316jsCompare e1 e2 op = parens ("_N.cmp(" ++ e1 ++ "," ++ e2 ++ ").ctor" ++ op)
318jsCompare e1 e2 op = parens ("_N.cmp(" ++ e1 ++ "," ++ e2 ++ ").ctor" ++ op)
320+-- todo: this is incorrect. Operators come in prefixed by their module now.
318binop (o:p) e1 e2
321binop (o:p) e1 e2
319 | isAlpha o || '_' == o = (o:p) ++ parens e1 ++ parens e2
322 | isAlpha o || '_' == o = (o:p) ++ parens e1 ++ parens e2
320 | otherwise =
323 | otherwise =