@@ -10,9 +10,10 @@ import qualified Data.Set as Set
10import Language.ECMAScript3.PrettyPrint
10import Language.ECMAScript3.PrettyPrint
11import Language.ECMAScript3.Syntax
11import Language.ECMAScript3.Syntax
13−import Generate.JavaScript.Helpers
13+import Generate.JavaScript.Helpers as Help
14import qualified Generate.Cases as Case
14import qualified Generate.Cases as Case
15import qualified Generate.JavaScript.Ports as Port
15import qualified Generate.JavaScript.Ports as Port
16+import qualified Generate.JavaScript.Variable as Var
16import qualified Generate.Markdown as MD
17import qualified Generate.Markdown as MD
18import AST.Annotation
19import AST.Annotation
@@ -23,62 +24,52 @@ import qualified AST.Module as Module
23import qualified AST.Helpers as Help
24import qualified AST.Helpers as Help
24import AST.Literal
25import AST.Literal
25import qualified AST.Pattern as P
26import qualified AST.Pattern as P
26−import AST.PrettyPrint (renderPretty)
27import qualified AST.Variable as Var
27import qualified AST.Variable as Var
29varDecl :: String -> Expression () -> VarDecl ()
29varDecl :: String -> Expression () -> VarDecl ()
30varDecl x expr =
30varDecl x expr =
31 VarDecl () (var x) (Just expr)
31 VarDecl () (var x) (Just expr)
33−include :: String -> String -> VarDecl ()
33+internalImports :: String -> [VarDecl ()]
34−include alias moduleName =
35− varDecl alias (obj (moduleName ++ ".make") <| ref "_elm")
37−internalImports :: String -> Statement ()
38internalImports name =
34internalImports name =
40− [ varDecl "_N" (obj "Elm.Native")
35+ [ varDecl "_N" (obj ["Elm","Native"])
41− , include "_U" "_N.Utils"
36+ , include "_U" "Utils"
42− , include "_L" "_N.List"
37+ , include "_L" "List"
43− , include "_A" "_N.Array"
38+ , include "_A" "Array"
44− , include "_E" "_N.Error"
39+ , include "_E" "Error"
45− , varDecl "$moduleName" (string name)
40+ , varDecl Help.localModuleName (string name)
43+ include :: String -> String -> VarDecl ()
44+ include alias modul =
45+ varDecl alias (obj ["_N", modul, "make"] <| ref "_elm")
47+_Utils :: String -> Expression ()
48+_Utils x = obj ["_U", x]
50+_List :: String -> Expression ()
51+_List x = obj ["_L", x]
48literal :: Literal -> Expression ()
53literal :: Literal -> Expression ()
49literal lit =
54literal lit =
50 case lit of
55 case lit of
51− Chr c -> obj "_U.chr" <| string [c]
56+ Chr c -> _Utils "chr" <| string [c]
52 Str s -> string s
57 Str s -> string s
53 IntNum n -> IntLit () n
58 IntNum n -> IntLit () n
54 FloatNum n -> NumLit () n
59 FloatNum n -> NumLit () n
55 Boolean b -> BoolLit () b
60 Boolean b -> BoolLit () b
57−canonical :: Var.Canonical -> Expression ()
58−canonical (Var.Canonical home name) =
59− case Help.isOp name of
60− True -> BracketRef () (dotSep (home' ++ ["_op"])) (string name)
61− False -> dotSep (home' ++ [map (swap '\'' '$') name])
63− swap from to c = if c == from then to else c
69− Var.Module path -> [ map (swap '.' '$') path ]
71expression :: Canonical.Expr -> State Int (Expression ())
62expression :: Canonical.Expr -> State Int (Expression ())
72expression (A region expr) =
63expression (A region expr) =
73 case expr of
64 case expr of
74− Var var -> return $ canonical var
65+ Var var -> return $ Var.canonical var
76 Literal lit -> return $ literal lit
67 Literal lit -> return $ literal lit
78 Range lo hi ->
69 Range lo hi ->
79 do lo' <- expression lo
70 do lo' <- expression lo
80 hi' <- expression hi
71 hi' <- expression hi
81− return $ obj "_L.range" `call` [lo',hi']
72+ return $ _List "range" `call` [lo',hi']
83 Access e x ->
74 Access e x ->
84 do e' <- expression e
75 do e' <- expression e
@@ -86,19 +77,19 @@ expression (A region expr) =
87 Remove e x ->
78 Remove e x ->
88 do e' <- expression e
79 do e' <- expression e
89− return $ obj "_U.remove" `call` [string x, e']
80+ return $ _Utils "remove" `call` [string x, e']
91 Insert e x v ->
82 Insert e x v ->
92 do v' <- expression v
83 do v' <- expression v
93 e' <- expression e
84 e' <- expression e
94− return $ obj "_U.insert" `call` [string x, v', e']
85+ return $ _Utils "insert" `call` [string x, v', e']
96 Modify e fs ->
87 Modify e fs ->
97 do e' <- expression e
88 do e' <- expression e
98 fs' <- forM fs $ \(f,v) -> do
89 fs' <- forM fs $ \(f,v) -> do
99 v' <- expression v
90 v' <- expression v
100 return $ ArrayLit () [string f, v']
91 return $ ArrayLit () [string f, v']
101− return $ obj "_U.replace" `call` [ArrayLit () fs', e']
92+ return $ _Utils "replace" `call` [ArrayLit () fs', e']
103 Record fields ->
94 Record fields ->
104 do fields' <- forM fields $ \(f,e) -> do
95 do fields' <- forM fields $ \(f,e) -> do
@@ -122,7 +113,7 @@ expression (A region expr) =
123 depattern (args, body) pattern =
114 depattern (args, body) pattern =
124 case pattern of
115 case pattern of
125− P.Var x -> return (args ++ [x], body)
116+ P.Var x -> return (args ++ [ Var.varName x ], body)
126 _ -> do arg <- Case.newVar
117 _ -> do arg <- Case.newVar
127 return ( args ++ [arg]
118 return ( args ++ [arg]
128 , A ann (Case (A ann (localVar arg)) [(pattern, body)]))
119 , A ann (Case (A ann (localVar arg)) [(pattern, body)]))
@@ -161,7 +152,7 @@ expression (A region expr) =
161 (A _ (Var (Var.Canonical (Var.Module "Basics") "otherwise")), _) ->
152 (A _ (Var (Var.Canonical (Var.Module "Basics") "otherwise")), _) ->
162 safeIfs branches'
153 safeIfs branches'
163 (A _ (Literal (Boolean True)), _) -> safeIfs branches'
154 (A _ (Literal (Boolean True)), _) -> safeIfs branches'
164− _ -> ifs branches' (obj "_E.If" `call` [ ref "$moduleName", string (renderPretty region) ])
155+ _ -> ifs branches' (throw "If" region)
166 safeIfs branches = ifs (init branches) (snd (last branches))
157 safeIfs branches = ifs (init branches) (snd (last branches))
167 ifs branches finally = foldr iff finally branches
158 ifs branches finally = foldr iff finally branches
@@ -181,7 +172,7 @@ expression (A region expr) =
182 ExplicitList es ->
173 ExplicitList es ->
183 do es' <- mapM expression es
174 do es' <- mapM expression es
184− return $ obj "_L.fromArray" <| ArrayLit () es'
175+ return $ _List "fromArray" <| ArrayLit () es'
186 Data name es ->
177 Data name es ->
187 do es' <- mapM expression es
178 do es' <- mapM expression es
@@ -192,7 +183,7 @@ expression (A region expr) =
193 Markdown uid doc es ->
184 Markdown uid doc es ->
194 do es' <- mapM expression es
185 do es' <- mapM expression es
195− return $ obj "Text.markdown" `call` (string md : string uid : es')
186+ return $ obj ["Text","markdown"] `call` (string md : string uid : es')
197 pad = "<div style=\"height:0;width:0;\"> </div>"
188 pad = "<div style=\"height:0;width:0;\"> </div>"
198 md = pad ++ MD.toHtml doc ++ pad
189 md = pad ++ MD.toHtml doc ++ pad
@@ -201,11 +192,11 @@ expression (A region expr) =
201 return $ ObjectLit () [(PropString () "src", literal (Str src))]
192 return $ ObjectLit () [(PropString () "src", literal (Str src))]
203 PortIn name tipe ->
194 PortIn name tipe ->
204− return $ obj "Native.Ports.portIn" `call` [ string name, Port.incoming tipe ]
195+ return $ obj ["Native","Ports","portIn"] `call` [ string name, Port.incoming tipe ]
206 PortOut name tipe value ->
197 PortOut name tipe value ->
207 do value' <- expression value
198 do value' <- expression value
208− return $ obj "Native.Ports.portOut" `call`
199+ return $ obj ["Native","Ports","portOut"] `call`
209 [ string name, Port.outgoing tipe, value' ]
200 [ string name, Port.outgoing tipe, value' ]
211definition :: Canonical.Def -> State Int [Statement ()]
202definition :: Canonical.Def -> State Int [Statement ()]
@@ -218,10 +209,10 @@ definition (Canonical.Definition pattern expr@(A region _) _) = do
218 let op = LBracket () (ref "_op") (string x) in
209 let op = LBracket () (ref "_op") (string x) in
219 return [ ExprStmt () $ AssignExpr () OpAssign op expr' ]
210 return [ ExprStmt () $ AssignExpr () OpAssign op expr' ]
220 | otherwise ->
211 | otherwise ->
221− return [ VarDeclStmt () [ assign x ] ]
212+ return [ VarDeclStmt () [ assign (Var.varName x) ] ]
223 P.Record fields ->
214 P.Record fields ->
224− let setField f = varDecl f (dotSep ["$",f]) in
215+ let setField f = varDecl f (obj ["$",f]) in
225 return [ VarDeclStmt () (assign "$" : map setField fields) ]
216 return [ VarDeclStmt () (assign "$" : map setField fields) ]
227 P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
218 P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
@@ -230,18 +221,18 @@ definition (Canonical.Definition pattern expr@(A region _) _) = do
230 vars = getVars patterns
221 vars = getVars patterns
231 getVars patterns =
222 getVars patterns =
232 case patterns of
223 case patterns of
233− P.Var x : rest -> (x:) `fmap` getVars rest
224+ P.Var x : rest -> (Var.varName x :) `fmap` getVars rest
234 [] -> Just []
225 [] -> Just []
235 _ -> Nothing
226 _ -> Nothing
237− decl x n = varDecl x (dotSep ["$","_" ++ show n])
228+ decl x n = varDecl x (obj ["$","_" ++ show n])
238 setup vars
229 setup vars
239 | Help.isTuple name = assign "$" : vars
230 | Help.isTuple name = assign "$" : vars
240 | otherwise = assign "_raw" : safeAssign : vars
231 | otherwise = assign "_raw" : safeAssign : vars
242− safeAssign = varDecl "$" (CondExpr () if' (obj "_raw") exception)
233+ safeAssign = varDecl "$" (CondExpr () if' (ref "_raw") exception)
243− if' = InfixExpr () OpStrictEq (obj "_raw.ctor") (string name)
234+ if' = InfixExpr () OpStrictEq (obj ["_raw","ctor"]) (string name)
244− exception = obj "_E.Case" `call` [ref "$moduleName", string (renderPretty region)]
235+ exception = Help.throw "Case" region
247 do defs' <- concat <$> mapM toDef vars
238 do defs' <- concat <$> mapM toDef vars
@@ -265,15 +256,15 @@ match region mtch =
265 _ -> False
256 _ -> False
267 access name
258 access name
268− | any isLiteral clauses = obj name
259+ | any isLiteral clauses = obj [name]
269− | otherwise = dotSep (split name ++ ["ctor"])
260+ | otherwise = obj (Help.splitDots name ++ ["ctor"])
271 format isChars e
262 format isChars e
272 | or isChars = InfixExpr () OpAdd e (string "")
263 | or isChars = InfixExpr () OpAdd e (string "")
273 | otherwise = e
264 | otherwise = e
275 Case.Fail ->
266 Case.Fail ->
276− return [ ExprStmt () (obj "_E.Case" `call` [ref "$moduleName", string (renderPretty region)]) ]
267+ return [ ExprStmt () (Help.throw "Case" region) ]
278 Case.Break -> return [BreakStmt () Nothing]
269 Case.Break -> return [BreakStmt () Nothing]
@@ -314,22 +305,48 @@ generate modul =
314 show . prettyPrint $ setup "Elm" (names ++ ["make"]) ++
305 show . prettyPrint $ setup "Elm" (names ++ ["make"]) ++
315 [ assign ("Elm" : names ++ ["make"]) (function ["_elm"] programStmts) ]
306 [ assign ("Elm" : names ++ ["make"]) (function ["_elm"] programStmts) ]
317 names = Module.names modul
309 names = Module.names modul
311+ thisModule :: Expression ()
319− thisModule = dotSep ("_elm" : names ++ ["values"])
312+ thisModule = obj ("_elm" : names ++ ["values"])
314+ programStmts :: [Statement ()]
320 programStmts =
315 programStmts =
322− [ [ ExprStmt () $ string "use strict" ]
317+ [ [ ExprStmt () (string "use strict") ]
323 , setup "_elm" (names ++ ["values"])
318 , setup "_elm" (names ++ ["values"])
324 , [ IfSingleStmt () thisModule (ret thisModule) ]
319 , [ IfSingleStmt () thisModule (ret thisModule) ]
325− , [ internalImports (List.intercalate "." names) ]
320+ , [ VarDeclStmt () localVars ]
326− , map jsImport . Set.toList . Set.fromList . map fst $ Module.imports modul
321+ , body
327− , [ assign ["_op"] (ObjectLit () []) ]
328− , concat $ evalState (mapM definition . fst . flattenLets [] $ Module.program (Module.body modul)) 0
329 , [ jsExports ]
322 , [ jsExports ]
330 , [ ret thisModule ]
323 , [ ret thisModule ]
326+ localVars :: [VarDecl ()]
327+ localVars = varDecl "_op" (ObjectLit () []) :
328+ internalImports (Module.getName modul) ++
331+ explicitImports :: [VarDecl ()]
333+ map jsImport . Set.toList . Set.fromList . map fst $ Module.imports modul
335+ jsImport :: String -> VarDecl ()
337+ varDecl (Var.moduleName name) $
338+ obj ("Elm" : Help.splitDots name ++ ["make"]) <| ref "_elm"
340+ body :: [Statement ()]
341+ body = concat $ evalState defs 0
343+ defs = mapM definition . fst . flattenLets [] $ Module.program (Module.body modul)
345+ setup namespace path = map create paths
347+ create name = assign name (InfixExpr () OpLOr (obj name) (ObjectLit () []))
348+ paths = drop 2 . init . List.inits $ namespace : path
333 jsExports = assign ("_elm" : names ++ ["values"]) (ObjectLit () exs)
350 jsExports = assign ("_elm" : names ++ ["values"]) (ObjectLit () exs)
335 exs = map entry $ "_op" : concatMap extract (exports modul)
352 exs = map entry $ "_op" : concatMap extract (exports modul)
@@ -345,19 +362,11 @@ generate modul =
345 case path of
362 case path of
346 [x] -> VarDeclStmt () [ varDecl x expr ]
363 [x] -> VarDeclStmt () [ varDecl x expr ]
347 _ -> ExprStmt () $
364 _ -> ExprStmt () $
348− AssignExpr () OpAssign (LDot () (dotSep (init path)) (last path)) expr
365+ AssignExpr () OpAssign (LDot () (obj (init path)) (last path)) expr
351− assign [dolarize name] $ dotSep ("Elm" : Help.splitDots name ++ ["make"]) <| ref "_elm"
353− setup namespace path = map create paths
355− create name = assign name (InfixExpr () OpLOr (dotSep name) (ObjectLit () []))
356− paths = drop 2 . init . List.inits $ namespace : path
358binop :: Region -> Var.Canonical -> Canonical.Expr -> Canonical.Expr
367binop :: Region -> Var.Canonical -> Canonical.Expr -> Canonical.Expr
359 -> State Int (Expression ())
368 -> State Int (Expression ())
360−binop region (Var.Canonical home op) e1 e2 =
369+binop region func@(Var.Canonical home op) e1 e2 =
361 case (home, op) of
370 case (home, op) of
362 (Var.Module "Basics", ".") ->
371 (Var.Module "Basics", ".") ->
363 do es <- mapM expression (e1 : collect [] e2)
372 do es <- mapM expression (e1 : collect [] e2)
@@ -371,7 +380,7 @@ binop region (Var.Canonical home op) e1 e2 =
371 (Var.Module "List", "++") ->
380 (Var.Module "List", "++") ->
372 do e1' <- expression e1
381 do e1' <- expression e1
373 e2' <- expression e2
382 e2' <- expression e2
374− return $ obj "_L.append" `call` [e1', e2']
383+ return $ _List "append" `call` [e1', e2']
376 (Var.BuiltIn, "::") ->
385 (Var.BuiltIn, "::") ->
377 expression (A region (Data "::" [e1,e2]))
386 expression (A region (Data "::" [e1,e2]))
@@ -381,12 +390,12 @@ binop region (Var.Canonical home op) e1 e2 =
381 e2' <- expression e2
390 e2' <- expression e2
382 return $ case Map.lookup op basicOps of
391 return $ case Map.lookup op basicOps of
383 Just f -> f e1' e2'
392 Just f -> f e1' e2'
384− Nothing -> ref "A2" `call` [ func, e1', e2' ]
393+ Nothing -> ref "A2" `call` [ Var.canonical func, e1', e2' ]
387 do e1' <- expression e1
396 do e1' <- expression e1
388 e2' <- expression e2
397 e2' <- expression e2
389− return (ref "A2" `call` [ func, e1', e2' ])
398+ return (ref "A2" `call` [ Var.canonical func, e1', e2' ])
392 collect es e =
401 collect es e =
@@ -395,14 +404,6 @@ binop region (Var.Canonical home op) e1 e2 =
395 collect (es ++ [e1]) e2
404 collect (es ++ [e1]) e2
396 _ -> es ++ [e]
405 _ -> es ++ [e]
398− func | Help.isOp op = BracketRef () (dotSep (path ++ ["_op"])) (string op)
399− | otherwise = dotSep (path ++ [op])
404− Var.Module m -> [dolarize m]
406 basicOps = Map.fromList (infixOps ++ specialOps)
407 basicOps = Map.fromList (infixOps ++ specialOps)
408 infixOps =
409 infixOps =
@@ -416,10 +417,10 @@ binop region (Var.Canonical home op) e1 e2 =
418 specialOps =
419 specialOps =
419− [ (,) "^" $ \a b -> obj "Math.pow" `call` [a,b]
420+ [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
420 , (,) "|>" $ flip (<|)
421 , (,) "|>" $ flip (<|)
421− , (,) "==" $ \a b -> obj "_U.eq" `call` [a,b]
422+ , (,) "==" $ \a b -> _Utils "eq" `call` [a,b]
422− , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (obj "_U.eq" `call` [a,b])
423+ , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (_Utils "eq" `call` [a,b])
423 , (,) "<" $ cmp OpLT 0
424 , (,) "<" $ cmp OpLT 0
424 , (,) ">" $ cmp OpGT 0
425 , (,) ">" $ cmp OpGT 0
425 , (,) "<=" $ cmp OpLT 1
426 , (,) "<=" $ cmp OpLT 1
@@ -427,4 +428,4 @@ binop region (Var.Canonical home op) e1 e2 =
427 , (,) "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
428 , (,) "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
430− cmp op n a b = InfixExpr () op (obj "_U.cmp" `call` [a,b]) (IntLit () n)
431+ cmp op n a b = InfixExpr () op (_Utils "cmp" `call` [a,b]) (IntLit () n)