1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
9import Prelude hiding (cycle)
10import Control.Monad (foldM)
11import qualified Data.List as List
12import qualified Data.Map as Map
13import qualified Data.Set as Set
16import qualified AST.Canonical as Can
17import qualified AST.Optimized as Opt
18import qualified AST.Module.Name as ModuleName
19import qualified AST.Utils.Type as Type
20import qualified Canonicalize.Effects as Effects
21import qualified Elm.Name as N
22import qualified Optimize.Expression as Expr
23import qualified Optimize.Names as Names
24import qualified Optimize.Port as Port
25import qualified Reporting.Annotation as A
26import qualified Reporting.Error.Main as E
27import qualified Reporting.Region as R
28import qualified Reporting.Result as Result
29import qualified Reporting.Warning as W
37 Result.Result i w E.Error a
41 Map.Map N.Name Can.Annotation
44optimize :: Annotations -> Can.Module -> Result i [W.Warning] Opt.Graph
45optimize annotations (Can.Module home _ _ decls unions aliases _ effects) =
46 addDecls home annotations decls $
47 addEffects home effects $
48 addUnions home unions $
49 addAliases home aliases $
50 Opt.Graph Map.empty Map.empty Map.empty
58 Map.Map Opt.Global Opt.Node
61addUnions :: ModuleName.Canonical -> Map.Map N.Name Can.Union -> Opt.Graph -> Opt.Graph
62addUnions home unions (Opt.Graph mains nodes fields) =
63 Opt.Graph mains (Map.foldr (addUnion home) nodes unions) fields
66addUnion :: ModuleName.Canonical -> Can.Union -> Nodes -> Nodes
67addUnion home (Can.Union _ ctors _ opts) nodes =
68 List.foldl' (addCtorNode home opts) nodes ctors
71addCtorNode :: ModuleName.Canonical -> Can.CtorOpts -> Nodes -> Can.Ctor -> Nodes
72addCtorNode home opts nodes (Can.Ctor name index numArgs _) =
76 Can.Normal -> Opt.Ctor index numArgs
78 Can.Enum -> Opt.Enum index
80 Map.insert (Opt.Global home name) node nodes
87addAliases :: ModuleName.Canonical -> Map.Map N.Name Can.Alias -> Opt.Graph -> Opt.Graph
88addAliases home aliases graph =
89 Map.foldrWithKey (addAlias home) graph aliases
92addAlias :: ModuleName.Canonical -> N.Name -> Can.Alias -> Opt.Graph -> Opt.Graph
93addAlias home name (Can.Alias _ tipe) graph@(Opt.Graph mains nodes fieldCounts) =
95 Can.TRecord fields Nothing ->
98 Opt.Function (map fst (Can.fieldsToList fields)) $ Opt.Record $
99 Map.mapWithKey (\field _ -> Opt.VarLocal field) fields
102 Opt.Define function Set.empty
106 (Map.insert (Opt.Global home name) node nodes)
107 (Map.foldrWithKey addRecordCtorField fieldCounts fields)
113addRecordCtorField :: N.Name -> Can.FieldType -> Map.Map N.Name Int -> Map.Map N.Name Int
114addRecordCtorField name _ fields =
115 Map.insertWith (+) name 1 fields
122addEffects :: ModuleName.Canonical -> Can.Effects -> Opt.Graph -> Opt.Graph
123addEffects home effects graph@(Opt.Graph mains nodes fields) =
129 Map.foldrWithKey (addPort home) graph ports
131 Can.Manager _ _ _ manager ->
133 fx = Opt.Global home "$fx$"
134 cmd = Opt.Global home "command"
135 sub = Opt.Global home "subscription"
140 Map.insert cmd link $
141 Map.insert fx (Opt.Manager Opt.Cmd) nodes
144 Map.insert sub link $
145 Map.insert fx (Opt.Manager Opt.Sub) nodes
148 Map.insert cmd link $
149 Map.insert sub link $
150 Map.insert fx (Opt.Manager Opt.Fx) nodes
152 Opt.Graph mains newNodes fields
155addPort :: ModuleName.Canonical -> N.Name -> Can.Port -> Opt.Graph -> Opt.Graph
156addPort home name port_ graph =
158 Can.Incoming _ payloadType _ ->
160 (deps, fields, decoder) = Names.run (Port.toDecoder payloadType)
161 node = Opt.PortIncoming decoder deps
163 addToGraph (Opt.Global home name) node fields graph
165 Can.Outgoing _ payloadType _ ->
167 (deps, fields, encoder) = Names.run (Port.toEncoder payloadType)
168 node = Opt.PortOutgoing encoder deps
170 addToGraph (Opt.Global home name) node fields graph
177addToGraph :: Opt.Global -> Opt.Node -> Map.Map N.Name Int -> Opt.Graph -> Opt.Graph
178addToGraph name node fields (Opt.Graph mains nodes fieldCounts) =
181 (Map.insert name node nodes)
182 (Map.unionWith (+) fields fieldCounts)
189addDecls :: ModuleName.Canonical -> Annotations -> Can.Decls -> Opt.Graph -> Result i [W.Warning] Opt.Graph
190addDecls home annotations decls graph =
192 Can.Declare def subDecls ->
193 addDecls home annotations subDecls =<< addDef home annotations def graph
195 Can.DeclareRec defs subDecls ->
196 case findMain defs of
198 addDecls home annotations subDecls (addRecDefs home defs graph)
201 Result.throw $ E.BadCycle region (map defToName defs)
203 Can.SaveTheEnvironment ->
207findMain :: [Can.Def] -> Maybe R.Region
215 Can.Def (A.At region name) _ _ ->
216 if name == N.main then Just region else findMain rest
218 Can.TypedDef (A.At region name) _ _ _ _ ->
219 if name == N.main then Just region else findMain rest
222defToName :: Can.Def -> N.Name
225 Can.Def (A.At _ name) _ _ -> name
226 Can.TypedDef (A.At _ name) _ _ _ _ -> name
233addDef :: ModuleName.Canonical -> Annotations -> Can.Def -> Opt.Graph -> Result i [W.Warning] Opt.Graph
234addDef home annotations def graph =
236 Can.Def (A.At region name) args body ->
237 do let (Can.Forall _ tipe) = annotations ! name
238 Result.warn $ W.MissingTypeAnnotation region name tipe
239 addDefHelp region annotations home name args body graph
241 Can.TypedDef (A.At region name) _ typedArgs body _ ->
242 addDefHelp region annotations home name (map fst typedArgs) body graph
245addDefHelp :: R.Region -> Annotations -> ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Graph -> Result i w Opt.Graph
246addDefHelp region annotations home name args body graph@(Opt.Graph mains nodes fieldCounts) =
247 if name /= N.main then
248 Result.ok (addDefNode home name args body Set.empty graph)
251 (Can.Forall _ tipe) = annotations ! name
253 addMain (deps, fields, main) =
255 newMains = Map.insert home main mains
256 newFields = Map.unionWith (+) fields fieldCounts
258 addDefNode home name args body deps $
259 Opt.Graph newMains nodes newFields
261 case Type.deepDealias tipe of
262 Can.TType hm nm [_] | hm == ModuleName.virtualDom && nm == N.node ->
263 Result.ok $ addMain $ Names.run $
264 Names.registerKernel N.virtualDom Opt.Static
266 Can.TType hm nm [flags, message, _] | hm == ModuleName.platform && nm == N.program ->
267 case Effects.checkPayload flags of
269 Result.ok $ addMain $ Names.run $
270 Opt.Dynamic message <$> Port.toFlagsDecoder flags
272 Left (subType, invalidPayload) ->
273 Result.throw (E.BadFlags region subType invalidPayload)
276 Result.throw (E.BadType region tipe)
279addDefNode :: ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Set.Set Opt.Global -> Opt.Graph -> Opt.Graph
280addDefNode home name args body mainDeps graph =
282 (deps, fields, def) =
286 Expr.optimize Set.empty body
289 do (argNames, destructors) <- Expr.destructArgs args
290 obody <- Expr.optimize Set.empty body
291 pure $ Opt.Function argNames $
292 foldr Opt.Destruct obody destructors
294 addToGraph (Opt.Global home name) (Opt.Define def (Set.union deps mainDeps)) fields graph
303 { _values :: [(N.Name, Opt.Expr)]
304 , _graph :: Opt.Graph
308addRecDefs :: ModuleName.Canonical -> [Can.Def] -> Opt.Graph -> Opt.Graph
309addRecDefs home defs graph =
311 cycleValues = foldr addValueName Set.empty defs
312 dummyName = Opt.Global home (N.toCompositeName (Set.toList cycleValues))
314 (deps, fields, State cyclicValuePairs newGraph) =
316 foldM (addRecDef home dummyName cycleValues) (State [] graph) defs
318 addToGraph dummyName (Opt.Cycle cyclicValuePairs deps) fields newGraph
321addValueName :: Can.Def -> Set.Set N.Name -> Set.Set N.Name
322addValueName def valueNames =
324 Can.Def (A.At _ name) [] _ ->
325 Set.insert name valueNames
327 Can.TypedDef (A.At _ name) _ [] _ _ ->
328 Set.insert name valueNames
338addRecDef :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> State -> Can.Def -> Names.Tracker State
339addRecDef home dummyName cycle state@(State values graph) def =
341 Can.Def (A.At _ name) [] body ->
342 addRecValue home dummyName cycle name body state
344 Can.TypedDef (A.At _ name) _ [] body _ ->
345 addRecValue home dummyName cycle name body state
349 (deps, fields, odef) =
350 Names.run (Expr.optimizePotentialTailCall cycle def)
352 pure $ State values $
355 let node = Opt.Define body deps in
356 addToGraph (Opt.Global home name) node fields graph
358 Opt.TailDef name args body ->
359 let node = Opt.DefineTailFunc args body deps in
360 addToGraph (Opt.Global home name) node fields graph
363addRecValue :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> N.Name -> Can.Expr -> State -> Names.Tracker State
364addRecValue home dummyName cycle name body (State values (Opt.Graph mains nodes fields)) =
365 do obody <- Expr.optimize cycle body
367 let global = Opt.Global home name
368 let node = Opt.Link dummyName
372 { _values = (name, obody) : values
373 , _graph = Opt.Graph mains (Map.insert global node nodes) fields
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list