@@ -14,15 +14,17 @@ import Generate.JavaScript.Helpers
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
16import qualified Generate.Markdown as MD
16import qualified Generate.Markdown as MD
17−import SourceSyntax.Annotation
18+import AST.Annotation
18−import SourceSyntax.Expression
19+import AST.Module
20+import AST.Expression.General
21+import qualified AST.Expression.Canonical as Canonical
19−import qualified SourceSyntax.Helpers as Help
22+import qualified AST.Module as Module
23+import qualified AST.Helpers as Help
20−import SourceSyntax.Literal
24+import AST.Literal
21−import SourceSyntax.Module
22−import qualified SourceSyntax.Pattern as P
25+import qualified AST.Pattern as P
23−import SourceSyntax.PrettyPrint (renderPretty)
26+import AST.PrettyPrint (renderPretty)
24−import qualified SourceSyntax.Variable as V
27+import qualified AST.Variable as Var
25−import qualified Transform.SafeNames as MakeSafe
27varDecl :: String -> Expression () -> VarDecl ()
29varDecl :: String -> Expression () -> VarDecl ()
28varDecl x expr =
30varDecl x expr =
@@ -51,10 +53,24 @@ literal lit =
51 FloatNum n -> NumLit () n
53 FloatNum n -> NumLit () n
52 Boolean b -> BoolLit () b
54 Boolean b -> BoolLit () b
56+canonical :: Var.Canonical -> Expression ()
57+canonical (Var.Canonical home name) =
58+ case Help.isOp name of
59+ True -> BracketRef () (dotSep (home' ++ ["_op"])) (string name)
60+ False -> dotSep (home' ++ [map (swap '\'' '$') name])
62+ swap from to c = if c == from then to else c
68+ Var.Module path -> [ map (swap '.' '$') path ]
54−expression :: Expr -> State Int (Expression ())
70+expression :: Canonical.Expr -> State Int (Expression ())
55expression (A region expr) =
71expression (A region expr) =
56 case expr of
72 case expr of
57− Var (V.Raw x) -> return $ obj x
73+ Var var -> return $ canonical var
59 Literal lit -> return $ literal lit
75 Literal lit -> return $ literal lit
@@ -108,7 +124,7 @@ expression (A region expr) =
108 P.Var x -> return (args ++ [x], body)
124 P.Var x -> return (args ++ [x], body)
109 _ -> do arg <- Case.newVar
125 _ -> do arg <- Case.newVar
110 return ( args ++ [arg]
126 return ( args ++ [arg]
111− , A ann (Case (A ann (rawVar arg)) [(pattern, body)]))
127+ , A ann (Case (A ann (localVar arg)) [(pattern, body)]))
113 (patterns, innerBody) = collect [p] e
129 (patterns, innerBody) = collect [p] e
@@ -141,7 +157,8 @@ expression (A region expr) =
141 MultiIf branches ->
157 MultiIf branches ->
142 do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
158 do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
143 return $ case last branches of
159 return $ case last branches of
160+ (A _ (Var (Var.Canonical (Var.Module "Basics") "otherwise")), _) ->
144− (A _ (Var (V.Raw "Basics.otherwise")), _) -> safeIfs branches'
161+ safeIfs branches'
145 (A _ (Literal (Boolean True)), _) -> safeIfs branches'
162 (A _ (Literal (Boolean True)), _) -> safeIfs branches'
146 _ -> ifs branches' (obj "_E.If" `call` [ ref "$moduleName", string (renderPretty region) ])
163 _ -> ifs branches' (obj "_E.If" `call` [ ref "$moduleName", string (renderPretty region) ])
@@ -153,7 +170,7 @@ expression (A region expr) =
153 do (tempVar,initialMatch) <- Case.toMatch cases
170 do (tempVar,initialMatch) <- Case.toMatch cases
154 (revisedMatch, stmt) <-
171 (revisedMatch, stmt) <-
155 case e of
172 case e of
156− A _ (Var (V.Raw x)) ->
173+ A _ (Var (Var.Canonical Var.Local x)) ->
157 return (Case.matchSubst [(tempVar,x)] initialMatch, [])
174 return (Case.matchSubst [(tempVar,x)] initialMatch, [])
159 do e' <- expression e
176 do e' <- expression e
@@ -187,8 +204,8 @@ expression (A region expr) =
187 return $ obj "Native.Ports.portOut" `call`
204 return $ obj "Native.Ports.portOut" `call`
188 [ string name, Port.outgoing tipe, value' ]
205 [ string name, Port.outgoing tipe, value' ]
190−definition :: Def -> State Int [Statement ()]
207+definition :: Canonical.Def -> State Int [Statement ()]
191−definition (Definition pattern expr@(A region _) _) = do
208+definition (Canonical.Definition pattern expr@(A region _) _) = do
192 expr' <- expression expr
209 expr' <- expression expr
193 let assign x = varDecl x expr'
210 let assign x = varDecl x expr'
194 case pattern of
211 case pattern of
@@ -203,7 +220,7 @@ definition (Definition pattern expr@(A region _) _) = do
203 let setField f = varDecl f (dotSep ["$",f]) in
220 let setField f = varDecl f (dotSep ["$",f]) in
204 return [ VarDeclStmt () (assign "$" : map setField fields) ]
221 return [ VarDeclStmt () (assign "$" : map setField fields) ]
206− P.Data name patterns | vars /= Nothing ->
223+ P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
207 return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
224 return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
209 vars = getVars patterns
226 vars = getVars patterns
@@ -227,9 +244,9 @@ definition (Definition pattern expr@(A region _) _) = do
227 return (VarDeclStmt () [assign "_"] : defs')
244 return (VarDeclStmt () [assign "_"] : defs')
229 vars = P.boundVarList pattern
246 vars = P.boundVarList pattern
230− mkVar = A region . rawVar
247+ mkVar = A region . localVar
231 toDef y = let expr = A region $ Case (mkVar "_") [(pattern, mkVar y)]
248 toDef y = let expr = A region $ Case (mkVar "_") [(pattern, mkVar y)]
232− in definition $ Definition (P.Var y) expr Nothing
249+ in definition $ Canonical.Definition (P.Var y) expr Nothing
234match :: Region -> Case.Match -> State Int [Statement ()]
251match :: Region -> Case.Match -> State Int [Statement ()]
235match region mtch =
252match region mtch =
@@ -279,40 +296,46 @@ clause region variable (Case.Clause value vars mtch) =
279 _ -> (,) False $ case value of
296 _ -> (,) False $ case value of
280 Right (Boolean b) -> BoolLit () b
297 Right (Boolean b) -> BoolLit () b
281 Right lit -> literal lit
298 Right lit -> literal lit
282− Left name -> string $ case List.elemIndices '.' name of
299+ Left (Var.Canonical _ name) ->
283− [] -> name
300+ string name
284− is -> drop (last is + 1) name
286−flattenLets :: [Def] -> Expr -> ([Def], Expr)
302+flattenLets :: [Canonical.Def] -> Canonical.Expr -> ([Canonical.Def], Canonical.Expr)
287flattenLets defs lexpr@(A _ expr) =
303flattenLets defs lexpr@(A _ expr) =
288 case expr of
304 case expr of
289 Let ds body -> flattenLets (defs ++ ds) body
305 Let ds body -> flattenLets (defs ++ ds) body
290 _ -> (defs, lexpr)
306 _ -> (defs, lexpr)
292−generate :: MetadataModule -> String
308+generate :: CanonicalModule -> String
293−generate unsafeModule =
309+generate modul =
294− show . prettyPrint $ setup (Just "Elm") (names modul ++ ["make"]) ++
310+ show . prettyPrint $ setup "Elm" (names ++ ["make"]) ++
295− [ assign ("Elm" : names modul ++ ["make"]) (function ["_elm"] programStmts) ]
311+ [ assign ("Elm" : names ++ ["make"]) (function ["_elm"] programStmts) ]
297− modul = MakeSafe.metadataModule unsafeModule
313+ names = Module.names modul
298− thisModule = dotSep ("_elm" : names modul ++ ["values"])
315+ thisModule = dotSep ("_elm" : names ++ ["values"])
299 programStmts =
316 programStmts =
301 [ [ ExprStmt () $ string "use strict" ]
318 [ [ ExprStmt () $ string "use strict" ]
302− , setup (Just "_elm") (names modul ++ ["values"])
319+ , setup "_elm" (names ++ ["values"])
303 , [ IfSingleStmt () thisModule (ret thisModule) ]
320 , [ IfSingleStmt () thisModule (ret thisModule) ]
304− , [ internalImports (List.intercalate "." (names modul)) ]
321+ , [ internalImports (List.intercalate "." names) ]
305− , concatMap jsImport . Set.toList . Set.fromList . map fst $ imports modul
322+ , map jsImport . Set.toList . Set.fromList . map fst $ Module.imports modul
306 , [ assign ["_op"] (ObjectLit () []) ]
323 , [ assign ["_op"] (ObjectLit () []) ]
307− , concat $ evalState (mapM definition . fst . flattenLets [] $ program modul) 0
324+ , concat $ evalState (mapM definition . fst . flattenLets [] $ Module.program (Module.body modul)) 0
308 , [ jsExports ]
325 , [ jsExports ]
309 , [ ret thisModule ]
326 , [ ret thisModule ]
312− jsExports = assign ("_elm" : names modul ++ ["values"]) (ObjectLit () exs)
329+ jsExports = assign ("_elm" : names ++ ["values"]) (ObjectLit () exs)
314− exs = map entry . filter (not . Help.isOp) $ "_op" : exports modul
331+ exs = map entry $ "_op" : concatMap extract (exports modul)
315 entry x = (prop x, ref x)
332 entry x = (prop x, ref x)
336+ Var.Value x | Help.isOp x -> []
338+ Var.ADT _ (Var.Listing ctors _) -> ctors
317 assign path expr =
340 assign path expr =
318 case path of
341 case path of
@@ -320,57 +343,66 @@ generate unsafeModule =
320 _ -> ExprStmt () $
343 _ -> ExprStmt () $
321 AssignExpr () OpAssign (LDot () (dotSep (init path)) (last path)) expr
344 AssignExpr () OpAssign (LDot () (dotSep (init path)) (last path)) expr
323− jsImport modul = setup Nothing path ++ [ include ]
346+ jsImport name =
325− path = Help.splitDots modul
326− include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "_elm"
347+ assign [dolarize name] $ dotSep ("Elm" : Help.splitDots name ++ ["make"]) <| ref "_elm"
328 setup namespace path = map create paths
349 setup namespace path = map create paths
330 create name = assign name (InfixExpr () OpLOr (dotSep name) (ObjectLit () []))
351 create name = assign name (InfixExpr () OpLOr (dotSep name) (ObjectLit () []))
331− paths = case namespace of
332− Nothing -> tail . init $ List.inits path
333− Just nmspc -> drop 2 . init . List.inits $ nmspc : path
352+ paths = drop 2 . init . List.inits $ namespace : path
354+binop :: Region -> Var.Canonical -> Canonical.Expr -> Canonical.Expr
335−binop :: Region -> String -> Expr -> Expr -> State Int (Expression ())
355+ -> State Int (Expression ())
336−binop region op e1 e2 =
356+binop region (Var.Canonical home op) e1 e2 =
337− case op of
357+ case (home, op) of
338− "Basics.." ->
358+ (Var.Module "Basics", ".") ->
339 do es <- mapM expression (e1 : collect [] e2)
359 do es <- mapM expression (e1 : collect [] e2)
340 return $ ["$"] ==> foldr (<|) (ref "$") es
360 return $ ["$"] ==> foldr (<|) (ref "$") es
362+ (Var.Module "Basics", "<|") ->
342 do e2' <- expression e2
363 do e2' <- expression e2
343 es <- mapM expression (collect [] e1)
364 es <- mapM expression (collect [] e1)
344 return $ foldr (<|) e2' es
365 return $ foldr (<|) e2' es
367+ (Var.Module "List", "++") ->
346 do e1' <- expression e1
368 do e1' <- expression e1
347 e2' <- expression e2
369 e2' <- expression e2
348 return $ obj "_L.append" `call` [e1', e2']
370 return $ obj "_L.append" `call` [e1', e2']
372+ (Var.BuiltIn, "::") ->
349− "::" -> expression (A region (Data "::" [e1,e2]))
373+ expression (A region (Data "::" [e1,e2]))
375+ (Var.Module "Basics", _) ->
351 do e1' <- expression e1
376 do e1' <- expression e1
352 e2' <- expression e2
377 e2' <- expression e2
353− return $ case Map.lookup op opDict of
378+ return $ case Map.lookup op basicOps of
354 Just f -> f e1' e2'
379 Just f -> f e1' e2'
355 Nothing -> ref "A2" `call` [ func, e1', e2' ]
380 Nothing -> ref "A2" `call` [ func, e1', e2' ]
383+ do e1' <- expression e1
384+ e2' <- expression e2
385+ return (ref "A2" `call` [ func, e1', e2' ])
357 collect es e =
388 collect es e =
358 case e of
389 case e of
390+ A _ (Binop (Var.Canonical (Var.Module "Basics") ".") e1 e2) ->
359− A _ (Binop op e1 e2) | op == "Basics.." -> collect (es ++ [e1]) e2
391+ collect (es ++ [e1]) e2
360 _ -> es ++ [e]
392 _ -> es ++ [e]
362− func | Help.isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
394+ func | Help.isOp op = BracketRef () (dotSep (path ++ ["_op"])) (string op)
363− | otherwise = dotSep parts
395+ | otherwise = dotSep (path ++ [op])
365− parts = Help.splitDots op
397+ path = case home of
366− operator = last parts
398+ Var.Local -> []
367−
399+ Var.BuiltIn -> []
368− opDict = Map.fromList (infixOps ++ specialOps)
400+ Var.Module m -> [dolarize m]
370− specialOp str func = [ (str, func), ("Basics." ++ str, func) ]
402+ basicOps = Map.fromList (infixOps ++ specialOps)
371− infixOp str op = specialOp str (InfixExpr () op)
373− infixOps = concat
404+ infixOps =
405+ let infixOp str op = (str, InfixExpr () op) in
374 [ infixOp "+" OpAdd
406 [ infixOp "+" OpAdd
375 , infixOp "-" OpSub
407 , infixOp "-" OpSub
376 , infixOp "*" OpMul
408 , infixOp "*" OpMul
@@ -379,16 +411,16 @@ binop region op e1 e2 =
379 , infixOp "||" OpLOr
411 , infixOp "||" OpLOr
382− specialOps = concat
414+ specialOps =
383− [ specialOp "^" $ \a b -> obj "Math.pow" `call` [a,b]
415+ [ (,) "^" $ \a b -> obj "Math.pow" `call` [a,b]
384− , specialOp "|>" $ flip (<|)
416+ , (,) "|>" $ flip (<|)
385− , specialOp "==" $ \a b -> obj "_U.eq" `call` [a,b]
417+ , (,) "==" $ \a b -> obj "_U.eq" `call` [a,b]
386− , specialOp "/=" $ \a b -> PrefixExpr () PrefixLNot (obj "_U.eq" `call` [a,b])
418+ , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (obj "_U.eq" `call` [a,b])
387− , specialOp "<" $ cmp OpLT 0
419+ , (,) "<" $ cmp OpLT 0
388− , specialOp ">" $ cmp OpGT 0
420+ , (,) ">" $ cmp OpGT 0
389− , specialOp "<=" $ cmp OpLT 1
421+ , (,) "<=" $ cmp OpLT 1
390− , specialOp ">=" $ cmp OpGT (-1)
422+ , (,) ">=" $ cmp OpGT (-1)
391− , specialOp "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
423+ , (,) "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
394 cmp op n a b = InfixExpr () op (obj "_U.cmp" `call` [a,b]) (IntLit () n)
426 cmp op n a b = InfixExpr () op (obj "_U.cmp" `call` [a,b]) (IntLit () n)