1-- | This module optimizes code in the simplified-JavaScript intermediate representation.
2--
3-- The following optimizations are supported:
4--
5--  * Collapsing nested blocks
6--
7--  * Tail call elimination
8--
9--  * Inlining of (>>=) and ret for the Eff monad
10--
11--  * Removal of unnecessary thunks
12--
13--  * Eta conversion
14--
15--  * Inlining variables
16--
17--  * Inline Prelude.($), Prelude.(#), Prelude.(++), Prelude.(!!)
18--
19--  * Inlining primitive JavaScript operators
20module Language.PureScript.CoreImp.Optimizer (optimize) where
21
22import Prelude.Compat
23
24import Control.Monad.Supply.Class (MonadSupply)
25import Language.PureScript.CoreImp.AST
26import Language.PureScript.CoreImp.Optimizer.Blocks
27import Language.PureScript.CoreImp.Optimizer.Common
28import Language.PureScript.CoreImp.Optimizer.Inliner
29import Language.PureScript.CoreImp.Optimizer.MagicDo
30import Language.PureScript.CoreImp.Optimizer.TCO
31import Language.PureScript.CoreImp.Optimizer.Unused
32
33-- | Apply a series of optimizer passes to simplified JavaScript code
34optimize :: MonadSupply m => AST -> m AST
35optimize js = do
36    js' <- untilFixedPoint (inlineFnComposition . inlineUnsafeCoerce . inlineUnsafePartial . tidyUp . applyAll
37      [ inlineCommonValues
38      , inlineCommonOperators
39      ]) js
40    untilFixedPoint (return . tidyUp) . tco . inlineST
41      =<< untilFixedPoint (return . magicDoST)
42      =<< untilFixedPoint (return . magicDoEff)
43      =<< untilFixedPoint (return . magicDoEffect) js'
44  where
45    tidyUp :: AST -> AST
46    tidyUp = applyAll
47      [ collapseNestedBlocks
48      , collapseNestedIfs
49      , removeCodeAfterReturnStatements
50      , removeUndefinedApp
51      , unThunk
52      , etaConvert
53      , evaluateIifes
54      , inlineVariables
55      ]
56
57untilFixedPoint :: (Monad m, Eq a) => (a -> m a) -> a -> m a
58untilFixedPoint f = go
59  where
60  go a = do
61   a' <- f a
62   if a' == a then return a' else go a'
63