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 _ _) nodes =
68 List.foldl' (addCtorNode home) nodes ctors
71addCtorNode :: ModuleName.Canonical -> Nodes -> Can.Ctor -> Nodes
72addCtorNode home nodes (Can.Ctor name index numArgs _) =
73 Map.insert (Opt.Global home name) (Opt.Ctor name index numArgs) nodes
80addAliases :: ModuleName.Canonical -> Map.Map N.Name Can.Alias -> Opt.Graph -> Opt.Graph
81addAliases home aliases graph =
82 Map.foldrWithKey (addAlias home) graph aliases
85addAlias :: ModuleName.Canonical -> N.Name -> Can.Alias -> Opt.Graph -> Opt.Graph
86addAlias home name (Can.Alias _ _ maybeFields) graph@(Opt.Graph mains nodes fieldCounts) =
94 Opt.Function (map fst fields) $ Opt.Record $
95 Map.fromList $ map toPair fields
98 Opt.Define function Set.empty
102 (Map.insert (Opt.Global home name) node nodes)
103 (foldr addRecordCtorField fieldCounts fields)
106toPair :: (N.Name, Can.Type) -> (N.Name, Opt.Expr)
108 ( field, Opt.VarLocal field )
111addRecordCtorField :: (N.Name, Can.Type) -> Map.Map N.Name Int -> Map.Map N.Name Int
112addRecordCtorField (name, _) fields =
113 Map.insertWith (+) name 1 fields
120addEffects :: ModuleName.Canonical -> Can.Effects -> Opt.Graph -> Opt.Graph
121addEffects home effects graph@(Opt.Graph mains nodes fields) =
127 Map.foldrWithKey (addPort home) graph ports
129 Can.Manager _ _ _ manager ->
131 fx = Opt.Global home "$fx$"
132 cmd = Opt.Global home "command"
133 sub = Opt.Global home "subscription"
138 Map.insert cmd link $
139 Map.insert fx (Opt.Manager Opt.Cmd) nodes
142 Map.insert sub link $
143 Map.insert fx (Opt.Manager Opt.Sub) nodes
146 Map.insert cmd link $
147 Map.insert sub link $
148 Map.insert fx (Opt.Manager Opt.Fx) nodes
150 Opt.Graph mains newNodes fields
153addPort :: ModuleName.Canonical -> N.Name -> Can.Port -> Opt.Graph -> Opt.Graph
154addPort home name port_ graph =
156 Can.Incoming _ payloadType _ ->
158 (deps, fields, decoder) = Names.run (Port.toDecoder payloadType)
159 node = Opt.PortIncoming decoder deps
161 addToGraph (Opt.Global home name) node fields graph
163 Can.Outgoing _ payloadType _ ->
165 (deps, fields, encoder) = Names.run (Port.toEncoder payloadType)
166 node = Opt.PortOutgoing encoder deps
168 addToGraph (Opt.Global home name) node fields graph
175addToGraph :: Opt.Global -> Opt.Node -> Map.Map N.Name Int -> Opt.Graph -> Opt.Graph
176addToGraph name node fields (Opt.Graph mains nodes fieldCounts) =
179 (Map.insert name node nodes)
180 (Map.unionWith (+) fields fieldCounts)
187addDecls :: ModuleName.Canonical -> Annotations -> Can.Decls -> Opt.Graph -> Result i [W.Warning] Opt.Graph
188addDecls home annotations decls graph =
190 Can.Declare def subDecls ->
191 addDecls home annotations subDecls =<< addDef home annotations def graph
193 Can.DeclareRec defs subDecls ->
194 case findMain defs of
196 addDecls home annotations subDecls (addRecDefs home defs graph)
199 Result.throw $ E.BadCycle region (map defToName defs)
201 Can.SaveTheEnvironment ->
205findMain :: [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
220defToName :: Can.Def -> N.Name
223 Can.Def (A.At _ name) _ _ -> name
224 Can.TypedDef (A.At _ name) _ _ _ _ -> name
231addDef :: ModuleName.Canonical -> Annotations -> Can.Def -> Opt.Graph -> Result i [W.Warning] Opt.Graph
232addDef home annotations def graph =
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
237 addDefHelp region annotations home name args body graph
239 Can.TypedDef (A.At region name) _ typedArgs body _ ->
240 addDefHelp region annotations home name (map fst typedArgs) body graph
243addDefHelp :: R.Region -> Annotations -> ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Graph -> Result i w Opt.Graph
244addDefHelp region annotations home name args body graph@(Opt.Graph mains nodes fieldCounts) =
245 if name /= N.main then
246 Result.ok (addDefNode home name args body Set.empty graph)
249 (Can.Forall _ tipe) = annotations ! name
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)
277addDefNode :: ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Set.Set Opt.Global -> Opt.Graph -> Opt.Graph
278addDefNode home name args body mainDeps graph =
280 (deps, fields, def) =
284 Expr.optimize Set.empty body
287 do (argNames, destructors) <- Expr.destructArgs args
288 obody <- Expr.optimize Set.empty body
289 pure $ Opt.Function argNames $
290 foldr Opt.Destruct obody destructors
292 addToGraph (Opt.Global home name) (Opt.Define def (Set.union deps mainDeps)) fields graph
301 { _values :: [(N.Name, Opt.Expr)]
302 , _graph :: Opt.Graph
306addRecDefs :: ModuleName.Canonical -> [Can.Def] -> Opt.Graph -> Opt.Graph
307addRecDefs home defs graph =
309 cycleValues = foldr addValueName Set.empty defs
310 dummyName = Opt.Global home (N.toCompositeName cycleValues)
312 (deps, fields, State cyclicValuePairs newGraph) =
314 foldM (addRecDef home dummyName cycleValues) (State [] graph) defs
316 addToGraph dummyName (Opt.Cycle cyclicValuePairs deps) fields newGraph
319addValueName :: Can.Def -> Set.Set N.Name -> Set.Set N.Name
320addValueName def valueNames =
322 Can.Def (A.At _ name) [] _ ->
323 Set.insert name valueNames
325 Can.TypedDef (A.At _ name) _ [] _ _ ->
326 Set.insert name valueNames
336addRecDef :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> State -> Can.Def -> Names.Tracker State
337addRecDef home dummyName cycle state@(State values graph) def =
339 Can.Def (A.At _ name) [] body ->
340 addRecValue home dummyName cycle name body state
342 Can.TypedDef (A.At _ name) _ [] body _ ->
343 addRecValue home dummyName cycle name body state
347 (deps, fields, odef) =
348 Names.run (Expr.optimizePotentialTailCall Set.empty def)
350 pure $ State values $
353 let node = Opt.Define body deps in
354 addToGraph (Opt.Global home name) node fields graph
356 Opt.TailDef name args body ->
357 let node = Opt.DefineTailFunc args body deps in
358 addToGraph (Opt.Global home name) node fields graph
361addRecValue :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> N.Name -> Can.Expr -> State -> Names.Tracker State
362addRecValue home dummyName cycle name body (State values (Opt.Graph mains nodes fields)) =
363 do obody <- Expr.optimize cycle body
365 let global = Opt.Global home name
366 let node = Opt.Link dummyName
370 { _values = (name, obody) : values
371 , _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