@@ -1,9 +1,12 @@
1module Optimize (optimize) where
1module Optimize (optimize) where
3import Control.Applicative
3import Control.Applicative
4+import Control.Arrow (second)
4import qualified Control.Monad as M
5import qualified Control.Monad as M
5import qualified Control.Monad.State as State
6import qualified Control.Monad.State as State
6import qualified Data.Map as Map
7import qualified Data.Map as Map
9+import qualified Data.Maybe as Maybe
7import qualified Data.Traversable as T
10import qualified Data.Traversable as T
9import qualified AST.Expression.General as Expr
12import qualified AST.Expression.General as Expr
@@ -13,6 +16,7 @@ import qualified AST.Module as Module
13import qualified AST.Module.Name as ModuleName
16import qualified AST.Module.Name as ModuleName
14import qualified AST.Pattern as P
17import qualified AST.Pattern as P
15import qualified AST.Variable as Var
18import qualified AST.Variable as Var
19+import Elm.Utils ((|>))
16import qualified Optimize.Cases as Cases
20import qualified Optimize.Cases as Cases
17import qualified Reporting.Annotation as A
21import qualified Reporting.Annotation as A
18import qualified Reporting.Region as R
22import qualified Reporting.Region as R
@@ -270,26 +274,8 @@ optimizeExpr context annExpr@(A.A region expression) =
270 do optDefs <- concat <$> T.traverse (optimizeDef Nothing) defs
274 do optDefs <- concat <$> T.traverse (optimizeDef Nothing) defs
271 Opt.Let optDefs <$> keepLooking body
275 Opt.Let optDefs <$> keepLooking body
273− Expr.Case expr rawBranches ->
277+ Expr.Case expr branches ->
274− let
278+ optimizeCase context region expr branches
275− indexify index (pattern, branch) =
280− (patterns, indexedBranches) =
281− unzip (zipWith indexify [0..] rawBranches)
284− Cases.compile (error "need a VariantDict") patterns
287− Map.fromList indexedBranches
290− <$> justConvert expr
291− <*> pure decisionTree
292− <*> T.traverse keepLooking branches
294 Expr.Data name exprs ->
280 Expr.Data name exprs ->
295 Opt.Data name <$> T.traverse justConvert exprs
281 Opt.Data name <$> T.traverse justConvert exprs
@@ -394,6 +380,115 @@ freshName =
394 return ("_p" ++ show uid)
380 return ("_p" ++ show uid)
389+ -> [(P.CanonicalPattern, Can.Expr)]
390+ -> Optimizer Opt.Expr
391+optimizeCase context region expr rawBranches =
393+ indexify index (pattern, branch) =
398+ do optBranches <- T.traverse (mapSnd (optimizeExpr context)) rawBranches
400+ case last optBranches of
401+ (A.A ann P.Anything, Opt.Call (Opt.Crash _ _) [arg]) ->
402+ do name <- freshName
403+ let newPattern = A.A ann (P.Var name)
404+ let newCall = Opt.Call (Opt.Crash region (Just name)) [arg]
405+ return (init optBranches ++ [(newPattern, newCall)])
410+ let (patterns, indexedBranches) =
411+ unzip (zipWith indexify [0..] crashBranches)
414+ Cases.compile (error "need a VariantDict") patterns
416+ optExpr <- optimizeExpr Nothing expr
418+ return (inlinedCase optExpr decisionTree indexedBranches)
423+ -> Cases.DecisionTree Cases.Jump
424+ -> [(Int, Opt.Expr)]
426+inlinedCase expr decisionTree jumpTargets =
429+ gatherSubstitutions decisionTree
431+ (jumps, sharedBranches) =
432+ unzip (map (toJumps substitutionDict) jumpTargets)
436+ (inlineJumps (Map.fromList jumps) decisionTree)
437+ (Maybe.catMaybes sharedBranches)
441+ :: Cases.DecisionTree Cases.Jump
442+ -> Map.Map Int [[(String, Cases.Path)]]
443+gatherSubstitutions decisionTree =
444+ case decisionTree of
445+ Cases.Decision _ edges fallback ->
447+ |> maybe id (:) fallback
448+ |> map gatherSubstitutions
449+ |> Map.unionsWith (++)
451+ Cases.Match (Cases.Jump target substitutions) ->
452+ Map.singleton target [substitutions]
456+ :: Map.Map Int [[(String, Cases.Path)]]
458+ -> ( (Int, Opt.Jump), Maybe (Int, Opt.Branch) )
459+toJumps substitutionDict (target, branch) =
460+ case substitutionDict ! target of
462+ ( (target, Opt.Inline (Opt.Branch substitutions branch))
466+ substitutions : _ ->
467+ ( (target, Opt.Jump target)
468+ , Just (target, Opt.Branch substitutions branch)
472+ error "it is not possible for there to be no substitutions"
476+ :: Map.Map Int Opt.Jump
477+ -> Cases.DecisionTree Cases.Jump
478+ -> Cases.DecisionTree Opt.Jump
479+inlineJumps jumpDict decisionTree =
482+ inlineJumps jumpDict
484+ case decisionTree of
485+ Cases.Decision test edges fallback ->
486+ Cases.Decision test (map (second go) edges) (fmap go fallback)
488+ Cases.Match (Cases.Jump target _) ->
489+ Cases.Match (jumpDict ! target)
397-- OPTIMIZE BINOPS
492-- OPTIMIZE BINOPS
399optimizeBinop
494optimizeBinop