1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
9import Control.Monad (foldM)
11import qualified AST.Canonical as Can
12import qualified AST.Optimized as Opt
13import qualified AST.Module.Name as ModuleName
14import qualified Data.Index as Index
15import qualified Elm.Name as N
16--import qualified Optimize.Case as Case
17import qualified Optimize.DecisionTree as DT
18import qualified Optimize.Names as Names
19--import qualified Optimize.Inline as Inline
20--import qualified Optimize.Port as Port
21import qualified Reporting.Annotation as A
22import qualified Reporting.Region as R
33optimizeExpr :: Can.Expr -> Names.Tracker Opt.Expr
34optimizeExpr (A.At region expression) =
37 pure (Opt.VarLocal name)
39 Can.VarTopLevel home name ->
40 Names.registerGlobal home name
42 Can.VarKernel home name ->
43 Names.registerKernel home (Opt.VarKernel home name)
45 Can.VarForeign home name _ ->
46 Names.registerGlobal home name
48 Can.VarDebug home name _ ->
49 Names.registerKernel N.debug (Opt.VarDebug name home region Nothing)
51 Can.VarOperator _ home name _ ->
52 Names.registerGlobal home name
64 pure (Opt.Float float)
67 Opt.List <$> traverse optimizeExpr entries
70 do func <- Names.registerGlobal ModuleName.basics N.negate
71 arg <- optimizeExpr expr
72 pure $ Opt.Call func [arg]
74 Can.Binop _ home name _ left right ->
75 do optFunc <- Names.registerGlobal home name
76 optLeft <- optimizeExpr left
77 optRight <- optimizeExpr right
78 return (Opt.Call optFunc [optLeft, optRight])
80 Can.Lambda args body ->
81 do (argNames, defss) <- destructArgs args
82 obody <- optimizeExpr body
84 Opt.Function argNames (foldr Opt.Let obody (concat defss))
89 <*> traverse optimizeExpr args
91 Can.If branches finally ->
93 optimizeBranch (condition, branch) =
95 <$> optimizeExpr condition
96 <*> optimizeExpr branch
99 <$> traverse optimizeBranch branches
100 <*> optimizeExpr finally
103 optimizeDef def =<< optimizeExpr body
105 Can.LetRec defs body ->
109 <$> optimizePotentialTailCall def
110 <*> optimizeExpr body
113 do obody <- optimizeExpr body
114 foldM (\bod def -> optimizeDef def bod) obody defs
116 Can.LetDestruct pattern expr body ->
117 do (name, defs) <- destruct pattern
118 oexpr <- optimizeExpr expr
119 obody <- optimizeExpr body
121 Opt.Let (Opt.Def name oexpr) (foldr Opt.Let obody defs)
123 Can.Case expr branches ->
126 Can.Accessor field ->
127 pure (Opt.Accessor field)
129 Can.Access record field ->
130 do optRecord <- optimizeExpr record
131 pure (Opt.Access optRecord field)
133 Can.Update record updates ->
135 <$> optimizeExpr record
136 <*> traverse optimizeExpr updates
139 Opt.Record <$> traverse optimizeExpr fields
142 Names.registerKernel N.utils Opt.Unit
144 Can.Tuple a b maybeC ->
145 Names.registerKernel N.utils Opt.Tuple
148 <*> traverse optimizeExpr maybeC
150 Can.Shader _ src _ ->
151 pure (Opt.Shader src)
158optimizeDef :: Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
159optimizeDef def body =
161 Can.Def (A.At _ name) args expr ->
162 optimizeDefHelp name args expr body
164 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
165 optimizeDefHelp name (map fst typedArgs) expr body
168optimizeDefHelp :: N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
169optimizeDefHelp name args expr body =
172 do oexpr <- optimizeExpr expr
173 pure $ Opt.Let (Opt.Def name oexpr) body
176 do (argNames, defss) <- destructArgs args
177 let func = Opt.Function argNames (foldr Opt.Let body (concat defss))
179 Opt.Let (Opt.Def name func) body
186destructArgs :: [Can.Pattern] -> Names.Tracker ([N.Name], [[Opt.Def]])
188 unzip <$> traverse destruct args
191destruct :: Can.Pattern -> Names.Tracker (N.Name, [Opt.Def])
192destruct pattern@(A.At _ ptrn) =
197 Can.PAlias subPattern name ->
198 do revDefs <- destructHelp (Opt.VarLocal name) subPattern []
199 pure (name, reverse revDefs)
202 do name <- Names.generate
203 revDefs <- destructHelp (Opt.VarLocal name) pattern []
204 pure (name, reverse revDefs)
207destructHelp :: Opt.Expr -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
208destructHelp root (A.At region pattern) revDefs =
214 pure (Opt.Def name root : revDefs)
216 Can.PRecord fields ->
219 Opt.Def field (Opt.Access root field)
221 pure (map toDef fields ++ revDefs)
223 Can.PAlias subPattern name ->
224 destructHelp (Opt.VarLocal name) subPattern $
225 Opt.Def name root : revDefs
230 Can.PTuple a b maybeC ->
231 do name <- Names.generate
232 let tuple = Opt.VarLocal name
233 let newRevDefs = Opt.Def name root : revDefs
236 destructHelp (Opt.CtorAccess tuple Index.second) b =<<
237 destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
240 destructHelp (Opt.CtorAccess tuple Index.third) c =<<
241 destructHelp (Opt.CtorAccess tuple Index.second) b =<<
242 destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
248 destructCons root hd (A.At region (Can.PList tl)) revDefs
251 destructCons root hd tl revDefs
262 Can.PCtor _ _ _ _ _ args ->
263 do name <- Names.generate
265 (destructCtorArg (Opt.VarLocal name))
266 (Opt.Def name root : revDefs)
270destructCons :: Opt.Expr -> Can.Pattern -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
271destructCons root hd tl revDefs =
272 do name <- Names.generate
273 let list = Opt.VarLocal name
274 destructHelp (Opt.CtorAccess list Index.first) hd =<<
275 destructHelp (Opt.CtorAccess list Index.second) tl (Opt.Def name root : revDefs)
278destructCtorArg :: Opt.Expr -> [Opt.Def] -> Can.PatternCtorArg -> Names.Tracker [Opt.Def]
279destructCtorArg root revDefs (Can.PatternCtorArg index _ arg) =
280 destructHelp (Opt.CtorAccess root index) arg revDefs
287optimizePotentialTailCall :: Can.Def -> Names.Tracker Opt.Def
288optimizePotentialTailCall def =
290 Can.Def (A.At _ name) args expr ->
291 do (argNames, defss) <- destructArgs args
292 toTailDef name argNames defss <$>
293 optimizeTailExpr name argNames expr
295 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
296 do (argNames, defss) <- destructArgs (map fst typedArgs)
297 toTailDef name argNames defss <$>
298 optimizeTailExpr name argNames expr
301optimizeTailExpr :: N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
302optimizeTailExpr name argNames locExpr@(A.At _ expression) =
304 Can.Call (A.At _ (Can.VarTopLevel _ funcName)) args ->
305 if funcName == name && length args == length argNames then
306 Opt.TailCall name argNames <$> traverse optimizeExpr args
310 Can.If branches finally ->
312 optimizeBranch (condition, branch) =
314 <$> optimizeExpr condition
315 <*> optimizeTailExpr name argNames branch
318 <$> traverse optimizeBranch branches
319 <*> optimizeTailExpr name argNames finally
322 optimizeDef def =<< optimizeTailExpr name argNames body
324 Can.LetRec defs body ->
328 <$> optimizePotentialTailCall def
329 <*> optimizeTailExpr name argNames body
332 do obody <- optimizeTailExpr name argNames body
333 foldM (\bod def -> optimizeDef def bod) obody defs
335 Can.LetDestruct pattern expr body ->
336 do (dname, defs) <- destruct pattern
337 oexpr <- optimizeExpr expr
338 obody <- optimizeTailExpr dname argNames body
340 Opt.Let (Opt.Def dname oexpr) (foldr Opt.Let obody defs)
342 Can.Case expr branches ->
353toTailDef :: N.Name -> [N.Name] -> [[Opt.Def]] -> Opt.Expr -> Opt.Def
354toTailDef name argNames defss body =
355 if hasTailCall body then
356 Opt.TailDef name argNames (foldr Opt.Let body (concat defss))
358 Opt.Def name (Opt.Function argNames (foldr Opt.Let body (concat defss)))
361hasTailCall :: Opt.Expr -> Bool
362hasTailCall expression =
364 Opt.TailCall _ _ _ ->
367 Opt.If branches finally ->
368 hasTailCall finally || any (hasTailCall . snd) branches
373 Opt.Case _ _ branches ->
374 any (hasTailCall . snd) branches
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