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 _ _ maybeFields) graph@(Opt.Graph mains nodes fieldCounts) =
101 Opt.Function (map fst fields) $ Opt.Record $
102 Map.fromList $ map toPair fields
105 Opt.Define function Set.empty
109 (Map.insert (Opt.Global home name) node nodes)
110 (foldr addRecordCtorField fieldCounts fields)
113toPair :: (N.Name, Can.Type) -> (N.Name, Opt.Expr)
115 ( field, Opt.VarLocal field )
118addRecordCtorField :: (N.Name, Can.Type) -> Map.Map N.Name Int -> Map.Map N.Name Int
119addRecordCtorField (name, _) fields =
120 Map.insertWith (+) name 1 fields
127addEffects :: ModuleName.Canonical -> Can.Effects -> Opt.Graph -> Opt.Graph
128addEffects home effects graph@(Opt.Graph mains nodes fields) =
134 Map.foldrWithKey (addPort home) graph ports
136 Can.Manager _ _ _ manager ->
138 fx = Opt.Global home "$fx$"
139 cmd = Opt.Global home "command"
140 sub = Opt.Global home "subscription"
145 Map.insert cmd link $
146 Map.insert fx (Opt.Manager Opt.Cmd) nodes
149 Map.insert sub link $
150 Map.insert fx (Opt.Manager Opt.Sub) nodes
153 Map.insert cmd link $
154 Map.insert sub link $
155 Map.insert fx (Opt.Manager Opt.Fx) nodes
157 Opt.Graph mains newNodes fields
160addPort :: ModuleName.Canonical -> N.Name -> Can.Port -> Opt.Graph -> Opt.Graph
161addPort home name port_ graph =
163 Can.Incoming _ payloadType _ ->
165 (deps, fields, decoder) = Names.run (Port.toDecoder payloadType)
166 node = Opt.PortIncoming decoder deps
168 addToGraph (Opt.Global home name) node fields graph
170 Can.Outgoing _ payloadType _ ->
172 (deps, fields, encoder) = Names.run (Port.toEncoder payloadType)
173 node = Opt.PortOutgoing encoder deps
175 addToGraph (Opt.Global home name) node fields graph
182addToGraph :: Opt.Global -> Opt.Node -> Map.Map N.Name Int -> Opt.Graph -> Opt.Graph
183addToGraph name node fields (Opt.Graph mains nodes fieldCounts) =
186 (Map.insert name node nodes)
187 (Map.unionWith (+) fields fieldCounts)
194addDecls :: ModuleName.Canonical -> Annotations -> Can.Decls -> Opt.Graph -> Result i [W.Warning] Opt.Graph
195addDecls home annotations decls graph =
197 Can.Declare def subDecls ->
198 addDecls home annotations subDecls =<< addDef home annotations def graph
200 Can.DeclareRec defs subDecls ->
201 case findMain defs of
203 addDecls home annotations subDecls (addRecDefs home defs graph)
206 Result.throw $ E.BadCycle region (map defToName defs)
208 Can.SaveTheEnvironment ->
212findMain :: [Can.Def] -> Maybe R.Region
220 Can.Def (A.At region name) _ _ ->
221 if name == N.main then Just region else findMain rest
223 Can.TypedDef (A.At region name) _ _ _ _ ->
224 if name == N.main then Just region else findMain rest
227defToName :: Can.Def -> N.Name
230 Can.Def (A.At _ name) _ _ -> name
231 Can.TypedDef (A.At _ name) _ _ _ _ -> name
238addDef :: ModuleName.Canonical -> Annotations -> Can.Def -> Opt.Graph -> Result i [W.Warning] Opt.Graph
239addDef home annotations def graph =
241 Can.Def (A.At region name) args body ->
242 do let (Can.Forall _ tipe) = annotations ! name
243 Result.warn $ W.MissingTypeAnnotation region name tipe
244 addDefHelp region annotations home name args body graph
246 Can.TypedDef (A.At region name) _ typedArgs body _ ->
247 addDefHelp region annotations home name (map fst typedArgs) body graph
250addDefHelp :: R.Region -> Annotations -> ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Graph -> Result i w Opt.Graph
251addDefHelp region annotations home name args body graph@(Opt.Graph mains nodes fieldCounts) =
252 if name /= N.main then
253 Result.ok (addDefNode home name args body Set.empty graph)
256 (Can.Forall _ tipe) = annotations ! name
258 addMain (deps, fields, main) =
260 newMains = Map.insert home main mains
261 newFields = Map.unionWith (+) fields fieldCounts
263 addDefNode home name args body deps $
264 Opt.Graph newMains nodes newFields
266 case Type.deepDealias tipe of
267 Can.TType hm nm [_] | hm == ModuleName.virtualDom && nm == N.node ->
268 Result.ok $ addMain $ Names.run $
269 Names.registerKernel N.virtualDom Opt.Static
271 Can.TType hm nm [flags, message, _] | hm == ModuleName.platform && nm == N.program ->
272 case Effects.checkPayload flags of
274 Result.ok $ addMain $ Names.run $
275 Opt.Dynamic message <$> Port.toFlagsDecoder flags
277 Left (subType, invalidPayload) ->
278 Result.throw (E.BadFlags region subType invalidPayload)
281 Result.throw (E.BadType region tipe)
284addDefNode :: ModuleName.Canonical -> N.Name -> [Can.Pattern] -> Can.Expr -> Set.Set Opt.Global -> Opt.Graph -> Opt.Graph
285addDefNode home name args body mainDeps graph =
287 (deps, fields, def) =
291 Expr.optimize Set.empty body
294 do (argNames, destructors) <- Expr.destructArgs args
295 obody <- Expr.optimize Set.empty body
296 pure $ Opt.Function argNames $
297 foldr Opt.Destruct obody destructors
299 addToGraph (Opt.Global home name) (Opt.Define def (Set.union deps mainDeps)) fields graph
308 { _values :: [(N.Name, Opt.Expr)]
309 , _graph :: Opt.Graph
313addRecDefs :: ModuleName.Canonical -> [Can.Def] -> Opt.Graph -> Opt.Graph
314addRecDefs home defs graph =
316 cycleValues = foldr addValueName Set.empty defs
317 dummyName = Opt.Global home (N.toCompositeName (Set.toList cycleValues))
319 (deps, fields, State cyclicValuePairs newGraph) =
321 foldM (addRecDef home dummyName cycleValues) (State [] graph) defs
323 addToGraph dummyName (Opt.Cycle cyclicValuePairs deps) fields newGraph
326addValueName :: Can.Def -> Set.Set N.Name -> Set.Set N.Name
327addValueName def valueNames =
329 Can.Def (A.At _ name) [] _ ->
330 Set.insert name valueNames
332 Can.TypedDef (A.At _ name) _ [] _ _ ->
333 Set.insert name valueNames
343addRecDef :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> State -> Can.Def -> Names.Tracker State
344addRecDef home dummyName cycle state@(State values graph) def =
346 Can.Def (A.At _ name) [] body ->
347 addRecValue home dummyName cycle name body state
349 Can.TypedDef (A.At _ name) _ [] body _ ->
350 addRecValue home dummyName cycle name body state
354 (deps, fields, odef) =
355 Names.run (Expr.optimizePotentialTailCall cycle def)
357 pure $ State values $
360 let node = Opt.Define body deps in
361 addToGraph (Opt.Global home name) node fields graph
363 Opt.TailDef name args body ->
364 let node = Opt.DefineTailFunc args body deps in
365 addToGraph (Opt.Global home name) node fields graph
368addRecValue :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> N.Name -> Can.Expr -> State -> Names.Tracker State
369addRecValue home dummyName cycle name body (State values (Opt.Graph mains nodes fields)) =
370 do obody <- Expr.optimize cycle body
372 let global = Opt.Global home name
373 let node = Opt.Link dummyName
377 { _values = (name, obody) : values
378 , _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