@@ -2,7 +2,7 @@
22{-# LANGUAGE OverloadedStrings #-}
33module Generate.JavaScript (generate) where
44
5−import Prelude hiding (init)
5+import Control.Monad (foldM)
66import Data.Monoid ((<>))
77import qualified Data.List as List
88import qualified Data.Map as Map
@@ -12,13 +12,14 @@ import qualified Data.ByteString.Builder as BS
1212
1313import qualified AST.Effects as Effects
1414import qualified AST.Expression.Optimized as Opt
15+import qualified AST.Kernel as Kernel
1516import qualified AST.Module.Name as ModuleName
1617import qualified AST.Variable as Var
1718import qualified Elm.Package as Pkg
1819import qualified Elm.Compiler.Objects.Internal as Obj
19−import qualified Generate.JavaScript.Builder as JS
20−import qualified Generate.JavaScript.Effects as Effects
21−import qualified Generate.JavaScript.Expression as JS
20+import qualified Generate.JavaScript.Builder as JsBuilder
21+import qualified Generate.JavaScript.Effects as JsEffects
22+import qualified Generate.JavaScript.Expression as JsExpr
2223import qualified Generate.JavaScript.Variable as JS
2324
2425
@@ -26,84 +27,91 @@ import qualified Generate.JavaScript.Variable as JS
2627-- GENERATE JAVASCRIPT
2728
2829
29−generate :: Obj.SymbolTable -> Obj.Graph -> Obj.Roots -> (Set.Set ModuleName.Canonical, BS.Builder)
30−generate symbols (Obj.Graph graph) roots =
30+generate :: Obj.Graph -> Obj.Roots -> BS.Builder
31+generate graph roots =
3132 let
32− (State builders _ kernels effects table) =
33− List.foldl' (crawl graph) (init symbols) (Obj.toGlobals roots)
33+ (State builders _ _ effects table) =
34+ List.foldl' (crawl graph) initialState (Obj.toGlobals roots)
3435
3536 managers =
36− fst $ JS.run table (Effects.generate effects)
37−
38− javascript =
39− List.foldl' (\rest stmt -> JS.encodeUtf8 stmt <> rest) managers builders
37+ fst $ JS.run table (JsEffects.generate effects)
4038 in
41− (kernels, javascript)
39+ List.foldl' (\rest stmt -> stmt <> rest) managers builders
4240
4341
4442
45−-- DCE STATE
43+-- CRAWL STATE
4644
4745
4846data State =
4947 State
50− { _stmts :: [JS.Stmt]
51− , _seen :: Set.Set Var.Global
52− , _kernels :: Set.Set ModuleName.Canonical
48+ { _builders :: [BS.Builder]
49+ , _seenDecls :: Set.Set Var.Global
50+ , _seenKernels :: Set.Set ModuleName.Raw
5351 , _effects :: Map.Map ModuleName.Canonical Effects.ManagerType
5452 , _table :: JS.Table
5553 }
5654
5755
58−init :: Obj.SymbolTable -> State
59−init symbols =
60− State [] Set.empty Set.empty Map.empty (JS.init symbols)
61−
62−
56+initialState :: State
57+initialState =
58+ State [] Set.empty Set.empty Map.empty JS.emptyTable
6359
64−-- DEAD CODE ELIMINATION
6560
6661
67−type Graph = Map.Map Var.Global Opt.Decl
62+-- CRAWL
6863
6964
70−crawl :: Graph -> State -> Var.Global -> State
71−crawl graph state@(State js seen kernels effects table) name@(Var.Global home _) =
72− if Set.member name seen then
65+crawl :: Obj.Graph -> State -> Var.Global -> State
66+crawl graph@(Obj.Graph decls kernels) state@(State _ seenDecls seenKernels _ _) name@(Var.Global home _) =
67+ if Set.member name seenDecls then
7368 state
7469
7570 else if home == virtualDomDebug then
7671 state
7772
7873 else
79− case Map.lookup name graph of
74+ case Map.lookup name decls of
8075 Just decl ->
8176 crawlDecl graph name decl state
8277
8378 Nothing ->
84− if ModuleName.canonicalIsKernel home then
85− State js seen (Set.insert home kernels) effects table
86− else
87− error (crawlError name)
79+ let
80+ kernelModule =
81+ ModuleName._module home
82+ in
83+ if Set.member kernelModule seenKernels then
84+ state
85+ else
86+ case Map.lookup kernelModule kernels of
87+ Just info ->
88+ crawlKernel graph kernelModule info state
89+
90+ Nothing ->
91+ error (crawlError name)
92+
93+
8894
95+-- CRAWL DECL
8996
90−crawlDecl :: Graph -> Var.Global -> Opt.Decl -> State -> State
97+
98+crawlDecl :: Obj.Graph -> Var.Global -> Opt.Decl -> State -> State
9199crawlDecl graph var@(Var.Global home name) (Opt.Decl direct indirect fx body) state1 =
92100 let
93101 state2 =
94− state1 { _seen = Set.insert var (_seen state1) }
102+ state1 { _seenDecls = Set.insert var (_seenDecls state1) }
95103
96− (State stmts seen kernels effects table) =
104+ (State builders seenDecls seenKernels effects table) =
97105 Set.foldl' (crawl graph) state2 direct
98106
99107 (stmt, newTable) =
100− JS.run table (JS.generateDecl home name body)
108+ JS.run table (JsExpr.generateDecl home name body)
101109
102110 state4 =
103111 State
104− { _stmts = stmt : stmts
105− , _seen = seen
106− , _kernels = kernels
112+ { _builders = JsBuilder.stmtToBuilder stmt : builders
113+ , _seenDecls = seenDecls
114+ , _seenKernels = seenKernels
107115 , _effects = maybe id (Map.insert home) fx effects
108116 , _table = newTable
109117 }
@@ -111,13 +119,57 @@ crawlDecl graph var@(Var.Global home name) (Opt.Decl direct indirect fx body) st
111119 Set.foldl' (crawl graph) state4 indirect
112120
113121
122+
123+-- CRAWL KERNEL
124+
125+
126+crawlKernel :: Obj.Graph -> ModuleName.Raw -> Kernel.Info -> State -> State
127+crawlKernel graph name (Kernel.Info imports chunks) state1 =
128+ let
129+ state2 =
130+ state1 { _seenKernels = Set.insert name (_seenKernels state1) }
131+
132+ (State builders seenDecls seenKernels effects table) =
133+ List.foldl' (crawl graph) state2 (map toCoreGlobal imports)
134+
135+ (builder, newTable) =
136+ JS.run table (foldM chunkToBuilder mempty chunks)
137+ in
138+ State
139+ { _builders = builder : builders
140+ , _seenDecls = seenDecls
141+ , _seenKernels = seenKernels
142+ , _effects = effects
143+ , _table = newTable
144+ }
145+
146+
147+toCoreGlobal :: ( ModuleName.Raw, Text.Text ) -> Var.Global
148+toCoreGlobal (home, name) =
149+ Var.Global (ModuleName.inCore home) name
150+
151+
152+chunkToBuilder :: BS.Builder -> Kernel.Chunk -> JS.Generator BS.Builder
153+chunkToBuilder builder chunk =
154+ case chunk of
155+ Kernel.JS javascript ->
156+ return $ BS.byteString javascript <> builder
157+
158+ Kernel.Var home name ->
159+ do expr <- JS.global (Var.Global (ModuleName.inCore home) name)
160+ return $ JsBuilder.exprToBuilder expr <> builder
161+
162+
163+-- CRAWL HELPERS
164+
165+
114166crawlError :: Var.Global -> String
115167crawlError (Var.Global (ModuleName.Canonical pkg home) name) =
116168 Text.unpack $
117169 "compiler bug manifesting in Generate.JavaScript\n"
118− <> "could not find " <> Pkg.toText pkg <> " " <> ModuleName.toText home <> "." <> name <> "\n"
119− <> "please report at <https://github.com/elm-lang/elm-compiler/issues>\n"
120− <> "try to make an <http://sscce.org/> that demonstrates the issue!"
170+ <> "Could not find " <> Pkg.toText pkg <> " " <> ModuleName.toText home <> "." <> name <> "\n"
171+ <> "Please report at <https://github.com/elm-lang/elm-compiler/issues>\n"
172+ <> "Try to make an <http://sscce.org/> that demonstrates the issue!"
121173
122174
123175virtualDomDebug :: ModuleName.Canonical