@@ -1,8 +1,7 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Optimize.Module
3module Optimize.Module
5− , optimize
4+ ( optimize
@@ -12,49 +11,56 @@ import Control.Monad (foldM)
12import qualified Data.List as List
11import qualified Data.List as List
13import qualified Data.Map as Map
12import qualified Data.Map as Map
14import qualified Data.Set as Set
13import qualified Data.Set as Set
16import qualified AST.Canonical as Can
16import qualified AST.Canonical as Can
17import qualified AST.Optimized as Opt
17import qualified AST.Optimized as Opt
18import qualified AST.Module.Name as ModuleName
18import qualified AST.Module.Name as ModuleName
19+import qualified AST.Utils.Type as Type
20+import qualified Canonicalize.Effects as Effects
19import qualified Elm.Name as N
21import qualified Elm.Name as N
20import qualified Optimize.Expression as Expr
22import qualified Optimize.Expression as Expr
21import qualified Optimize.Names as Names
23import qualified Optimize.Names as Names
22import qualified Optimize.Port as Port
24import qualified Optimize.Port as Port
23import qualified Reporting.Annotation as A
25import qualified Reporting.Annotation as A
26+import qualified Reporting.Error.Main as E
27+import qualified Reporting.Region as R
28+import qualified Reporting.Result as Result
29+import qualified Reporting.Warning as W
27-- OPTIMIZE
33-- OPTIMIZE
30−data Graph =
36+type Result i w a =
31− Graph
37+ Result.Result i w E.Error a
32− { _fields :: Map.Map N.Name Int
37−type Nodes =
40+type Annotations =
38− Map.Map Opt.Global Opt.Node
41+ Map.Map N.Name Can.Annotation
41−optimize :: Can.Module -> Graph
44+optimize :: Annotations -> Can.Module -> Result i [W.Warning] Opt.Graph
42−optimize (Can.Module home _ _ decls unions aliases _ effects) =
45+optimize annotations (Can.Module home _ _ decls unions aliases _ effects) =
46+ addDecls home annotations decls $
43− addEffects home effects $
47+ addEffects home effects $
44− addUnions home unions $
48+ addUnions home unions $
45− addAliases home aliases $
49+ addAliases home aliases $
46− addDecls home decls $
47− Graph Map.empty Map.empty
50+ Opt.Graph Map.empty Map.empty Map.empty
58+ Map.Map Opt.Global Opt.Node
54−addUnions :: ModuleName.Canonical -> Map.Map N.Name Can.Union -> Graph -> Graph
61+addUnions :: ModuleName.Canonical -> Map.Map N.Name Can.Union -> Opt.Graph -> Opt.Graph
55−addUnions home unions (Graph fields nodes) =
62+addUnions home unions (Opt.Graph mains nodes fields) =
57− Map.foldr (addUnion home) nodes unions
63+ Opt.Graph mains (Map.foldr (addUnion home) nodes unions) fields
60addUnion :: ModuleName.Canonical -> Can.Union -> Nodes -> Nodes
66addUnion :: ModuleName.Canonical -> Can.Union -> Nodes -> Nodes
@@ -71,13 +77,13 @@ addCtorNode home nodes (Can.Ctor name index numArgs _) =
74−addAliases :: ModuleName.Canonical -> Map.Map N.Name Can.Alias -> Graph -> Graph
80+addAliases :: ModuleName.Canonical -> Map.Map N.Name Can.Alias -> Opt.Graph -> Opt.Graph
75addAliases home aliases graph =
81addAliases home aliases graph =
76 Map.foldrWithKey (addAlias home) graph aliases
82 Map.foldrWithKey (addAlias home) graph aliases
79−addAlias :: ModuleName.Canonical -> N.Name -> Can.Alias -> Graph -> Graph
85+addAlias :: ModuleName.Canonical -> N.Name -> Can.Alias -> Opt.Graph -> Opt.Graph
80−addAlias home name (Can.Alias _ _ maybeFields) graph@(Graph fieldCounts nodes) =
86+addAlias home name (Can.Alias _ _ maybeFields) graph@(Opt.Graph mains nodes fieldCounts) =
81 case maybeFields of
87 case maybeFields of
82 Nothing ->
88 Nothing ->
@@ -91,9 +97,10 @@ addAlias home name (Can.Alias _ _ maybeFields) graph@(Graph fieldCounts nodes) =
92 Opt.Define function Set.empty
98 Opt.Define function Set.empty
95− (foldr addOne fieldCounts fields)
101+ mains
96 (Map.insert (Opt.Global home name) node nodes)
102 (Map.insert (Opt.Global home name) node nodes)
103+ (foldr addOne fieldCounts fields)
99toPair :: N.Name -> (N.Name, Opt.Expr)
106toPair :: N.Name -> (N.Name, Opt.Expr)
@@ -110,8 +117,8 @@ addOne name fields =
110-- ADD EFFECTS
117-- ADD EFFECTS
113−addEffects :: ModuleName.Canonical -> Can.Effects -> Graph -> Graph
120+addEffects :: ModuleName.Canonical -> Can.Effects -> Opt.Graph -> Opt.Graph
114−addEffects home effects graph@(Graph fields nodes) =
121+addEffects home effects graph@(Opt.Graph mains nodes fields) =
115 case effects of
122 case effects of
116 Can.NoEffects ->
123 Can.NoEffects ->
@@ -120,30 +127,30 @@ addEffects home effects graph@(Graph fields nodes) =
120 Map.foldrWithKey (addPort home) graph ports
127 Map.foldrWithKey (addPort home) graph ports
122 Can.Manager _ _ _ manager ->
129 Can.Manager _ _ _ manager ->
125− fx = Opt.Global home "$fx$"
131+ fx = Opt.Global home "$fx$"
126− cmd = Opt.Global home "command"
132+ cmd = Opt.Global home "command"
127− sub = Opt.Global home "subscription"
133+ sub = Opt.Global home "subscription"
128− link = Opt.Link fx
134+ link = Opt.Link fx
130− case manager of
136+ case manager of
131− Can.Cmd _ ->
137+ Can.Cmd _ ->
132− Map.insert cmd link $
138+ Map.insert cmd link $
133− Map.insert fx (Opt.Manager Opt.Cmd) nodes
139+ Map.insert fx (Opt.Manager Opt.Cmd) nodes
135− Can.Sub _ ->
141+ Can.Sub _ ->
136− Map.insert sub link $
142+ Map.insert sub link $
137− Map.insert fx (Opt.Manager Opt.Sub) nodes
143+ Map.insert fx (Opt.Manager Opt.Sub) nodes
139− Can.Fx _ _ ->
145+ Can.Fx _ _ ->
140− Map.insert cmd link $
146+ Map.insert cmd link $
141− Map.insert sub link $
147+ Map.insert sub link $
142− Map.insert fx (Opt.Manager Opt.Fx) nodes
148+ Map.insert fx (Opt.Manager Opt.Fx) nodes
150+ Opt.Graph mains newNodes fields
146−addPort :: ModuleName.Canonical -> N.Name -> Can.Port -> Graph -> Graph
153+addPort :: ModuleName.Canonical -> N.Name -> Can.Port -> Opt.Graph -> Opt.Graph
147addPort home name port_ graph =
154addPort home name port_ graph =
148 case port_ of
155 case port_ of
149 Can.Incoming _ payloadType _ ->
156 Can.Incoming _ payloadType _ ->
@@ -162,86 +169,151 @@ addPort home name port_ graph =
175+addToGraph :: Opt.Global -> Opt.Node -> Map.Map N.Name Int -> Opt.Graph -> Opt.Graph
176+addToGraph name node fields (Opt.Graph mains nodes fieldCounts) =
179+ (Map.insert name node nodes)
180+ (Map.unionWith (+) fields fieldCounts)
165-- ADD DECLS
184-- ADD DECLS
168−addDecls :: ModuleName.Canonical -> Can.Decls -> Graph -> Graph
187+addDecls :: ModuleName.Canonical -> Annotations -> Can.Decls -> Opt.Graph -> Result i [W.Warning] Opt.Graph
169−addDecls home decls graph =
188+addDecls home annotations decls graph =
170 case decls of
189 case decls of
171 Can.Declare def subDecls ->
190 Can.Declare def subDecls ->
172− addDecls home subDecls (addDef home def graph)
191+ addDecls home annotations subDecls =<< addDef home annotations def graph
174 Can.DeclareRec defs subDecls ->
193 Can.DeclareRec defs subDecls ->
194+ case findMain defs of
175− addDecls home subDecls (addRecDefs home defs graph)
196+ addDecls home annotations subDecls (addRecDefs home defs graph)
199+ Result.throw $ E.BadCycle region (map defToName defs)
177 Can.SaveTheEnvironment ->
201 Can.SaveTheEnvironment ->
178− graph
202+ Result.ok graph
205+findMain :: [Can.Def] -> Maybe R.Region
213+ Can.Def (A.At region name) _ _ ->
214+ if name == N.main then Just region else findMain rest
216+ Can.TypedDef (A.At region name) _ _ _ _ ->
217+ if name == N.main then Just region else findMain rest
220+defToName :: Can.Def -> N.Name
223+ Can.Def (A.At _ name) _ _ -> name
224+ Can.TypedDef (A.At _ name) _ _ _ _ -> name
182-- ADD DEFS
228-- ADD DEFS
185−addDef :: ModuleName.Canonical -> Can.Def -> Graph -> Graph
231+addDef :: ModuleName.Canonical -> Annotations -> Can.Def -> Opt.Graph -> Result i [W.Warning] Opt.Graph
186−addDef home def graph =
232+addDef home annotations def graph =
187 case def of
233 case def of
188− Can.Def (A.At _ name) args body ->
234+ Can.Def (A.At region name) args body ->
235+ do let (Can.Forall _ tipe) = annotations ! name
236+ Result.warn $ W.MissingTypeAnnotation region name tipe
189− addDefHelp (Opt.Global home name) args body graph
237+ addDefHelp region annotations home name args body graph
191− Can.TypedDef (A.At _ name) _ typedArgs body _ ->
239+ Can.TypedDef (A.At region name) _ typedArgs body _ ->
192− addDefHelp (Opt.Global home name) (map fst typedArgs) body graph
240+ addDefHelp region annotations home name (map fst typedArgs) body graph
195−addDefHelp :: Opt.Global -> [Can.Pattern] -> Can.Expr -> Graph -> Graph
243+addDefHelp :: R.Region -> Annotations -> ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Graph -> Result i w Opt.Graph
196−addDefHelp name args body graph =
244+addDefHelp region annotations home name args body graph@(Opt.Graph mains nodes fieldCounts) =
197− case args of
245+ if name /= N.main then
198− [] ->
246+ Result.ok (addDefNode home name args body Set.empty graph)
200− (deps, fields, value) =
248+ let
201− Names.run (Expr.optimize Set.empty body)
249+ (Can.Forall _ tipe) = annotations ! name
203− addToGraph name (Opt.Define value deps) fields graph
205− _ ->
251+ addMain (deps, fields, main) =
253+ newMains = Map.insert home main mains
254+ newFields = Map.unionWith (+) fields fieldCounts
256+ addDefNode home name args body deps $
257+ Opt.Graph newMains nodes newFields
259+ case Type.deepDealias tipe of
260+ Can.TType hm nm [_] | hm == ModuleName.virtualDom && nm == N.node ->
261+ Result.ok $ addMain $ Names.run $
262+ Names.registerKernel N.browser Opt.Static
264+ Can.TType hm nm [flags, message, _] | hm == ModuleName.platform && nm == N.program ->
265+ case Effects.checkPayload flags of
267+ Result.ok $ addMain $ Names.run $
268+ Opt.Dynamic message <$> Port.toFlagsDecoder flags
270+ Left (subType, invalidPayload) ->
271+ Result.throw (E.BadFlags region subType invalidPayload)
274+ Result.throw (E.BadType region tipe)
277+addDefNode :: ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Set.Set Opt.Global -> Opt.Graph -> Opt.Graph
278+addDefNode home name args body mainDeps graph =
207− (deps, fields, function) =
280+ (deps, fields, def) =
208− Names.run $
281+ Names.run $
284+ Expr.optimize Set.empty body
209 do (argNames, destructors) <- Expr.destructArgs args
287 do (argNames, destructors) <- Expr.destructArgs args
210 obody <- Expr.optimize Set.empty body
288 obody <- Expr.optimize Set.empty body
211 pure $ Opt.Function argNames $
289 pure $ Opt.Function argNames $
212 foldr Opt.Destruct obody destructors
290 foldr Opt.Destruct obody destructors
214− addToGraph name (Opt.Define function deps) fields graph
292+ addToGraph (Opt.Global home name) (Opt.Define def (Set.union deps mainDeps)) fields graph
217−addToGraph :: Opt.Global -> Opt.Node -> Map.Map N.Name Int -> Graph -> Graph
218−addToGraph name node fields (Graph fieldCounts nodes) =
220− (Map.unionWith (+) fields fieldCounts)
221− (Map.insert name node nodes)
296+-- ADD RECURSIVE DEFS
225−-- ADD RECURSIVE DEFS
299+data State =
301+ { _values :: [(N.Name, Opt.Expr)]
302+ , _graph :: Opt.Graph
228−addRecDefs :: ModuleName.Canonical -> [Can.Def] -> Graph -> Graph
306+addRecDefs :: ModuleName.Canonical -> [Can.Def] -> Opt.Graph -> Opt.Graph
229addRecDefs home defs graph =
307addRecDefs home defs graph =
232− foldr addValueName Set.empty defs
309+ cycleValues = foldr addValueName Set.empty defs
235− Opt.Global home (N.toCompositeName cycleValues)
310+ dummyName = Opt.Global home (N.toCompositeName cycleValues)
237 (deps, fields, State cyclicValuePairs newGraph) =
312 (deps, fields, State cyclicValuePairs newGraph) =
238 Names.run $
313 Names.run $
239 foldM (addRecDef home dummyName cycleValues) (State [] graph) defs
314 foldM (addRecDef home dummyName cycleValues) (State [] graph) defs
242− Opt.Cycle cyclicValuePairs deps
244− addToGraph dummyName node fields newGraph
316+ addToGraph dummyName (Opt.Cycle cyclicValuePairs deps) fields newGraph
247addValueName :: Can.Def -> Set.Set N.Name -> Set.Set N.Name
319addValueName :: Can.Def -> Set.Set N.Name -> Set.Set N.Name
@@ -261,13 +333,6 @@ addValueName def valueNames =
261-- ADD RECURSIVE DEFS
333-- ADD RECURSIVE DEFS
266− { _values :: [(N.Name, Opt.Expr)]
271addRecDef :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> State -> Can.Def -> Names.Tracker State
336addRecDef :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> State -> Can.Def -> Names.Tracker State
272addRecDef home dummyName cycle state@(State values graph) def =
337addRecDef home dummyName cycle state@(State values graph) def =
273 case def of
338 case def of
@@ -294,11 +359,14 @@ addRecDef home dummyName cycle state@(State values graph) def =
296addRecValue :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> N.Name -> Can.Expr -> State -> Names.Tracker State
361addRecValue :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> N.Name -> Can.Expr -> State -> Names.Tracker State
297−addRecValue home dummyName cycle name body (State values (Graph fields nodes)) =
362+addRecValue home dummyName cycle name body (State values (Opt.Graph mains nodes fields)) =
298 do obody <- Expr.optimize cycle body
363 do obody <- Expr.optimize cycle body
365+ let global = Opt.Global home name
366+ let node = Opt.Link dummyName
301 { _values = (name, obody) : values
370 { _values = (name, obody) : values
302− , _graph = Graph fields $
371+ , _graph = Opt.Graph mains (Map.insert global node nodes) fields
303− Map.insert (Opt.Global home name) (Opt.Link dummyName) nodes