@@ -14,15 +14,17 @@ import Generate.JavaScript.Helpers
1414import qualified Generate.Cases as Case
1515import qualified Generate.JavaScript.Ports as Port
1616import qualified Generate.Markdown as MD
17−import SourceSyntax.Annotation
18−import SourceSyntax.Expression
19−import qualified SourceSyntax.Helpers as Help
20−import SourceSyntax.Literal
21−import SourceSyntax.Module
22−import qualified SourceSyntax.Pattern as P
23−import SourceSyntax.PrettyPrint (renderPretty)
24−import qualified SourceSyntax.Variable as V
25−import qualified Transform.SafeNames as MakeSafe
17+
18+import AST.Annotation
19+import AST.Module
20+import AST.Expression.General
21+import qualified AST.Expression.Canonical as Canonical
22+import qualified AST.Module as Module
23+import qualified AST.Helpers as Help
24+import AST.Literal
25+import qualified AST.Pattern as P
26+import AST.PrettyPrint (renderPretty)
27+import qualified AST.Variable as Var
2628
2729varDecl :: String -> Expression () -> VarDecl ()
2830varDecl x expr =
@@ -51,10 +53,24 @@ literal lit =
5153 FloatNum n -> NumLit () n
5254 Boolean b -> BoolLit () b
5355
54−expression :: Expr -> State Int (Expression ())
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])
61+ where
62+ swap from to c = if c == from then to else c
63+
64+ home' =
65+ case home of
66+ Var.Local -> []
67+ Var.BuiltIn -> []
68+ Var.Module path -> [ map (swap '.' '$') path ]
69+
70+expression :: Canonical.Expr -> State Int (Expression ())
5571expression (A region expr) =
5672 case expr of
57− Var (V.Raw x) -> return $ obj x
73+ Var var -> return $ canonical var
5874
5975 Literal lit -> return $ literal lit
6076
@@ -108,7 +124,7 @@ expression (A region expr) =
108124 P.Var x -> return (args ++ [x], body)
109125 _ -> do arg <- Case.newVar
110126 return ( args ++ [arg]
111− , A ann (Case (A ann (rawVar arg)) [(pattern, body)]))
127+ , A ann (Case (A ann (localVar arg)) [(pattern, body)]))
112128
113129 (patterns, innerBody) = collect [p] e
114130
@@ -141,7 +157,8 @@ expression (A region expr) =
141157 MultiIf branches ->
142158 do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
143159 return $ case last branches of
144− (A _ (Var (V.Raw "Basics.otherwise")), _) -> safeIfs branches'
160+ (A _ (Var (Var.Canonical (Var.Module "Basics") "otherwise")), _) ->
161+ safeIfs branches'
145162 (A _ (Literal (Boolean True)), _) -> safeIfs branches'
146163 _ -> ifs branches' (obj "_E.If" `call` [ ref "$moduleName", string (renderPretty region) ])
147164 where
@@ -153,7 +170,7 @@ expression (A region expr) =
153170 do (tempVar,initialMatch) <- Case.toMatch cases
154171 (revisedMatch, stmt) <-
155172 case e of
156− A _ (Var (V.Raw x)) ->
173+ A _ (Var (Var.Canonical Var.Local x)) ->
157174 return (Case.matchSubst [(tempVar,x)] initialMatch, [])
158175 _ ->
159176 do e' <- expression e
@@ -187,8 +204,8 @@ expression (A region expr) =
187204 return $ obj "Native.Ports.portOut" `call`
188205 [ string name, Port.outgoing tipe, value' ]
189206
190−definition :: Def -> State Int [Statement ()]
191−definition (Definition pattern expr@(A region _) _) = do
207+definition :: Canonical.Def -> State Int [Statement ()]
208+definition (Canonical.Definition pattern expr@(A region _) _) = do
192209 expr' <- expression expr
193210 let assign x = varDecl x expr'
194211 case pattern of
@@ -203,7 +220,7 @@ definition (Definition pattern expr@(A region _) _) = do
203220 let setField f = varDecl f (dotSep ["$",f]) in
204221 return [ VarDeclStmt () (assign "$" : map setField fields) ]
205222
206− P.Data name patterns | vars /= Nothing ->
223+ P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
207224 return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
208225 where
209226 vars = getVars patterns
@@ -227,9 +244,9 @@ definition (Definition pattern expr@(A region _) _) = do
227244 return (VarDeclStmt () [assign "_"] : defs')
228245 where
229246 vars = P.boundVarList pattern
230− mkVar = A region . rawVar
247+ mkVar = A region . localVar
231248 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
233250
234251match :: Region -> Case.Match -> State Int [Statement ()]
235252match region mtch =
@@ -279,40 +296,46 @@ clause region variable (Case.Clause value vars mtch) =
279296 _ -> (,) False $ case value of
280297 Right (Boolean b) -> BoolLit () b
281298 Right lit -> literal lit
282− Left name -> string $ case List.elemIndices '.' name of
283− [] -> name
284− is -> drop (last is + 1) name
299+ Left (Var.Canonical _ name) ->
300+ string name
285301
286−flattenLets :: [Def] -> Expr -> ([Def], Expr)
302+flattenLets :: [Canonical.Def] -> Canonical.Expr -> ([Canonical.Def], Canonical.Expr)
287303flattenLets defs lexpr@(A _ expr) =
288304 case expr of
289305 Let ds body -> flattenLets (defs ++ ds) body
290306 _ -> (defs, lexpr)
291307
292−generate :: MetadataModule -> String
293−generate unsafeModule =
294− show . prettyPrint $ setup (Just "Elm") (names modul ++ ["make"]) ++
295− [ assign ("Elm" : names modul ++ ["make"]) (function ["_elm"] programStmts) ]
308+generate :: CanonicalModule -> String
309+generate modul =
310+ show . prettyPrint $ setup "Elm" (names ++ ["make"]) ++
311+ [ assign ("Elm" : names ++ ["make"]) (function ["_elm"] programStmts) ]
296312 where
297− modul = MakeSafe.metadataModule unsafeModule
298− thisModule = dotSep ("_elm" : names modul ++ ["values"])
313+ names = Module.names modul
314+
315+ thisModule = dotSep ("_elm" : names ++ ["values"])
299316 programStmts =
300317 concat
301318 [ [ ExprStmt () $ string "use strict" ]
302− , setup (Just "_elm") (names modul ++ ["values"])
319+ , setup "_elm" (names ++ ["values"])
303320 , [ IfSingleStmt () thisModule (ret thisModule) ]
304− , [ internalImports (List.intercalate "." (names modul)) ]
305− , concatMap jsImport . Set.toList . Set.fromList . map fst $ imports modul
321+ , [ internalImports (List.intercalate "." names) ]
322+ , map jsImport . Set.toList . Set.fromList . map fst $ Module.imports modul
306323 , [ 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
308325 , [ jsExports ]
309326 , [ ret thisModule ]
310327 ]
311328
312− jsExports = assign ("_elm" : names modul ++ ["values"]) (ObjectLit () exs)
329+ jsExports = assign ("_elm" : names ++ ["values"]) (ObjectLit () exs)
313330 where
314− exs = map entry . filter (not . Help.isOp) $ "_op" : exports modul
331+ exs = map entry $ "_op" : concatMap extract (exports modul)
315332 entry x = (prop x, ref x)
333+ extract value =
334+ case value of
335+ Var.Alias _ -> []
336+ Var.Value x | Help.isOp x -> []
337+ | otherwise -> [x]
338+ Var.ADT _ (Var.Listing ctors _) -> ctors
316339
317340 assign path expr =
318341 case path of
@@ -320,57 +343,66 @@ generate unsafeModule =
320343 _ -> ExprStmt () $
321344 AssignExpr () OpAssign (LDot () (dotSep (init path)) (last path)) expr
322345
323− jsImport modul = setup Nothing path ++ [ include ]
324− where
325− path = Help.splitDots modul
326− include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "_elm"
346+ jsImport name =
347+ assign [dolarize name] $ dotSep ("Elm" : Help.splitDots name ++ ["make"]) <| ref "_elm"
327348
328349 setup namespace path = map create paths
329350 where
330351 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
334−
335−binop :: Region -> String -> Expr -> Expr -> State Int (Expression ())
336−binop region op e1 e2 =
337− case op of
338− "Basics.." ->
352+ paths = drop 2 . init . List.inits $ namespace : path
353+
354+binop :: Region -> Var.Canonical -> Canonical.Expr -> Canonical.Expr
355+ -> State Int (Expression ())
356+binop region (Var.Canonical home op) e1 e2 =
357+ case (home, op) of
358+ (Var.Module "Basics", ".") ->
339359 do es <- mapM expression (e1 : collect [] e2)
340360 return $ ["$"] ==> foldr (<|) (ref "$") es
341− "Basics.<|" ->
361+
362+ (Var.Module "Basics", "<|") ->
342363 do e2' <- expression e2
343364 es <- mapM expression (collect [] e1)
344365 return $ foldr (<|) e2' es
345− "List.++" ->
366+
367+ (Var.Module "List", "++") ->
346368 do e1' <- expression e1
347369 e2' <- expression e2
348370 return $ obj "_L.append" `call` [e1', e2']
349− "::" -> expression (A region (Data "::" [e1,e2]))
350− _ ->
371+
372+ (Var.BuiltIn, "::") ->
373+ expression (A region (Data "::" [e1,e2]))
374+
375+ (Var.Module "Basics", _) ->
351376 do e1' <- expression e1
352377 e2' <- expression e2
353− return $ case Map.lookup op opDict of
378+ return $ case Map.lookup op basicOps of
354379 Just f -> f e1' e2'
355380 Nothing -> ref "A2" `call` [ func, e1', e2' ]
381+
382+ _ ->
383+ do e1' <- expression e1
384+ e2' <- expression e2
385+ return (ref "A2" `call` [ func, e1', e2' ])
386+
356387 where
357388 collect es e =
358389 case e of
359− A _ (Binop op e1 e2) | op == "Basics.." -> collect (es ++ [e1]) e2
390+ A _ (Binop (Var.Canonical (Var.Module "Basics") ".") e1 e2) ->
391+ collect (es ++ [e1]) e2
360392 _ -> es ++ [e]
361393
362− func | Help.isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
363− | otherwise = dotSep parts
364− where
365− parts = Help.splitDots op
366− operator = last parts
367−
368− opDict = Map.fromList (infixOps ++ specialOps)
394+ func | Help.isOp op = BracketRef () (dotSep (path ++ ["_op"])) (string op)
395+ | otherwise = dotSep (path ++ [op])
396+ where
397+ path = case home of
398+ Var.Local -> []
399+ Var.BuiltIn -> []
400+ Var.Module m -> [dolarize m]
369401
370− specialOp str func = [ (str, func), ("Basics." ++ str, func) ]
371− infixOp str op = specialOp str (InfixExpr () op)
402+ basicOps = Map.fromList (infixOps ++ specialOps)
372403
373− infixOps = concat
404+ infixOps =
405+ let infixOp str op = (str, InfixExpr () op) in
374406 [ infixOp "+" OpAdd
375407 , infixOp "-" OpSub
376408 , infixOp "*" OpMul
@@ -379,16 +411,16 @@ binop region op e1 e2 =
379411 , infixOp "||" OpLOr
380412 ]
381413
382− specialOps = concat
383− [ specialOp "^" $ \a b -> obj "Math.pow" `call` [a,b]
384− , specialOp "|>" $ flip (<|)
385− , specialOp "==" $ \a b -> obj "_U.eq" `call` [a,b]
386− , specialOp "/=" $ \a b -> PrefixExpr () PrefixLNot (obj "_U.eq" `call` [a,b])
387− , specialOp "<" $ cmp OpLT 0
388− , specialOp ">" $ cmp OpGT 0
389− , specialOp "<=" $ cmp OpLT 1
390− , specialOp ">=" $ cmp OpGT (-1)
391− , specialOp "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
414+ specialOps =
415+ [ (,) "^" $ \a b -> obj "Math.pow" `call` [a,b]
416+ , (,) "|>" $ flip (<|)
417+ , (,) "==" $ \a b -> obj "_U.eq" `call` [a,b]
418+ , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (obj "_U.eq" `call` [a,b])
419+ , (,) "<" $ cmp OpLT 0
420+ , (,) ">" $ cmp OpGT 0
421+ , (,) "<=" $ cmp OpLT 1
422+ , (,) ">=" $ cmp OpGT (-1)
423+ , (,) "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
392424 ]
393425
394426 cmp op n a b = InfixExpr () op (obj "_U.cmp" `call` [a,b]) (IntLit () n)