@@ -2,7 +2,7 @@
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript (generate) where
3module Generate.JavaScript (generate) where
5−import Prelude hiding (init)
5+import Control.Monad (foldM)
6import Data.Monoid ((<>))
6import Data.Monoid ((<>))
7import qualified Data.List as List
7import qualified Data.List as List
8import qualified Data.Map as Map
8import qualified Data.Map as Map
@@ -12,13 +12,14 @@ import qualified Data.ByteString.Builder as BS
13import qualified AST.Effects as Effects
13import qualified AST.Effects as Effects
14import qualified AST.Expression.Optimized as Opt
14import qualified AST.Expression.Optimized as Opt
15+import qualified AST.Kernel as Kernel
15import qualified AST.Module.Name as ModuleName
16import qualified AST.Module.Name as ModuleName
16import qualified AST.Variable as Var
17import qualified AST.Variable as Var
17import qualified Elm.Package as Pkg
18import qualified Elm.Package as Pkg
18import qualified Elm.Compiler.Objects.Internal as Obj
19import qualified Elm.Compiler.Objects.Internal as Obj
19−import qualified Generate.JavaScript.Builder as JS
20+import qualified Generate.JavaScript.Builder as JsBuilder
20−import qualified Generate.JavaScript.Effects as Effects
21+import qualified Generate.JavaScript.Effects as JsEffects
21−import qualified Generate.JavaScript.Expression as JS
22+import qualified Generate.JavaScript.Expression as JsExpr
22import qualified Generate.JavaScript.Variable as JS
23import qualified Generate.JavaScript.Variable as JS
@@ -26,84 +27,91 @@ import qualified Generate.JavaScript.Variable as JS
26-- GENERATE JAVASCRIPT
27-- GENERATE JAVASCRIPT
29−generate :: Obj.SymbolTable -> Obj.Graph -> Obj.Roots -> (Set.Set ModuleName.Canonical, BS.Builder)
30+generate :: Obj.Graph -> Obj.Roots -> BS.Builder
30−generate symbols (Obj.Graph graph) roots =
31+generate graph roots =
32− (State builders _ kernels effects table) =
33+ (State builders _ _ effects table) =
33− List.foldl' (crawl graph) (init symbols) (Obj.toGlobals roots)
34+ List.foldl' (crawl graph) initialState (Obj.toGlobals roots)
35 managers =
36 managers =
36− fst $ JS.run table (Effects.generate effects)
37+ fst $ JS.run table (JsEffects.generate effects)
39− List.foldl' (\rest stmt -> JS.encodeUtf8 stmt <> rest) managers builders
41− (kernels, javascript)
39+ List.foldl' (\rest stmt -> stmt <> rest) managers builders
45−-- DCE STATE
43+-- CRAWL STATE
48data State =
46data State =
50− { _stmts :: [JS.Stmt]
48+ { _builders :: [BS.Builder]
51− , _seen :: Set.Set Var.Global
49+ , _seenDecls :: Set.Set Var.Global
52− , _kernels :: Set.Set ModuleName.Canonical
50+ , _seenKernels :: Set.Set ModuleName.Raw
53 , _effects :: Map.Map ModuleName.Canonical Effects.ManagerType
51 , _effects :: Map.Map ModuleName.Canonical Effects.ManagerType
54 , _table :: JS.Table
52 , _table :: JS.Table
58−init :: Obj.SymbolTable -> State
56+initialState :: State
59−init symbols =
57+initialState =
60− State [] Set.empty Set.empty Map.empty (JS.init symbols)
58+ State [] Set.empty Set.empty Map.empty JS.emptyTable
64−-- DEAD CODE ELIMINATION
67−type Graph = Map.Map Var.Global Opt.Decl
62+-- CRAWL
70−crawl :: Graph -> State -> Var.Global -> State
65+crawl :: Obj.Graph -> State -> Var.Global -> State
71−crawl graph state@(State js seen kernels effects table) name@(Var.Global home _) =
66+crawl graph@(Obj.Graph decls kernels) state@(State _ seenDecls seenKernels _ _) name@(Var.Global home _) =
72− if Set.member name seen then
67+ if Set.member name seenDecls then
75 else if home == virtualDomDebug then
70 else if home == virtualDomDebug then
79− case Map.lookup name graph of
74+ case Map.lookup name decls of
80 Just decl ->
75 Just decl ->
81 crawlDecl graph name decl state
76 crawlDecl graph name decl state
83 Nothing ->
78 Nothing ->
84− if ModuleName.canonicalIsKernel home then
79+ let
85− State js seen (Set.insert home kernels) effects table
80+ kernelModule =
86− else
81+ ModuleName._module home
83+ if Set.member kernelModule seenKernels then
86+ case Map.lookup kernelModule kernels of
88+ crawlKernel graph kernelModule info state
87− error (crawlError name)
91+ error (crawlError name)
90−crawlDecl :: Graph -> Var.Global -> Opt.Decl -> State -> State
98+crawlDecl :: Obj.Graph -> Var.Global -> Opt.Decl -> State -> State
91crawlDecl graph var@(Var.Global home name) (Opt.Decl direct indirect fx body) state1 =
99crawlDecl graph var@(Var.Global home name) (Opt.Decl direct indirect fx body) state1 =
94− state1 { _seen = Set.insert var (_seen state1) }
102+ state1 { _seenDecls = Set.insert var (_seenDecls state1) }
96− (State stmts seen kernels effects table) =
104+ (State builders seenDecls seenKernels effects table) =
97 Set.foldl' (crawl graph) state2 direct
105 Set.foldl' (crawl graph) state2 direct
99 (stmt, newTable) =
107 (stmt, newTable) =
100− JS.run table (JS.generateDecl home name body)
108+ JS.run table (JsExpr.generateDecl home name body)
104− { _stmts = stmt : stmts
112+ { _builders = JsBuilder.stmtToBuilder stmt : builders
105− , _seen = seen
113+ , _seenDecls = seenDecls
106− , _kernels = kernels
114+ , _seenKernels = seenKernels
107 , _effects = maybe id (Map.insert home) fx effects
115 , _effects = maybe id (Map.insert home) fx effects
108 , _table = newTable
116 , _table = newTable
@@ -111,13 +119,57 @@ crawlDecl graph var@(Var.Global home name) (Opt.Decl direct indirect fx body) st
111 Set.foldl' (crawl graph) state4 indirect
119 Set.foldl' (crawl graph) state4 indirect
126+crawlKernel :: Obj.Graph -> ModuleName.Raw -> Kernel.Info -> State -> State
127+crawlKernel graph name (Kernel.Info imports chunks) state1 =
130+ state1 { _seenKernels = Set.insert name (_seenKernels state1) }
132+ (State builders seenDecls seenKernels effects table) =
133+ List.foldl' (crawl graph) state2 (map toCoreGlobal imports)
135+ (builder, newTable) =
136+ JS.run table (foldM chunkToBuilder mempty chunks)
139+ { _builders = builder : builders
140+ , _seenDecls = seenDecls
141+ , _seenKernels = seenKernels
142+ , _effects = effects
147+toCoreGlobal :: ( ModuleName.Raw, Text.Text ) -> Var.Global
148+toCoreGlobal (home, name) =
149+ Var.Global (ModuleName.inCore home) name
152+chunkToBuilder :: BS.Builder -> Kernel.Chunk -> JS.Generator BS.Builder
153+chunkToBuilder builder chunk =
155+ Kernel.JS javascript ->
156+ return $ BS.byteString javascript <> builder
158+ Kernel.Var home name ->
159+ do expr <- JS.global (Var.Global (ModuleName.inCore home) name)
160+ return $ JsBuilder.exprToBuilder expr <> builder
114crawlError :: Var.Global -> String
166crawlError :: Var.Global -> String
115crawlError (Var.Global (ModuleName.Canonical pkg home) name) =
167crawlError (Var.Global (ModuleName.Canonical pkg home) name) =
116 Text.unpack $
168 Text.unpack $
117 "compiler bug manifesting in Generate.JavaScript\n"
169 "compiler bug manifesting in Generate.JavaScript\n"
118− <> "could not find " <> Pkg.toText pkg <> " " <> ModuleName.toText home <> "." <> name <> "\n"
170+ <> "Could not find " <> Pkg.toText pkg <> " " <> ModuleName.toText home <> "." <> name <> "\n"
119− <> "please report at <https://github.com/elm-lang/elm-compiler/issues>\n"
171+ <> "Please report at <https://github.com/elm-lang/elm-compiler/issues>\n"
120− <> "try to make an <http://sscce.org/> that demonstrates the issue!"
172+ <> "Try to make an <http://sscce.org/> that demonstrates the issue!"
123virtualDomDebug :: ModuleName.Canonical
175virtualDomDebug :: ModuleName.Canonical