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
16import qualified Optimize.Case as Case
17import qualified Optimize.Names as Names
18import qualified Reporting.Annotation as A
29optimizeExpr :: Can.Expr -> Names.Tracker Opt.Expr
30optimizeExpr (A.At region expression) =
33 pure (Opt.VarLocal name)
35 Can.VarTopLevel home name ->
36 Names.registerGlobal home name
38 Can.VarKernel home name ->
39 Names.registerKernel home (Opt.VarKernel home name)
41 Can.VarForeign home name _ ->
42 Names.registerGlobal home name
44 Can.VarDebug home name _ ->
45 Names.registerKernel N.debug (Opt.VarDebug name home region Nothing)
47 Can.VarOperator _ home name _ ->
48 Names.registerGlobal home name
60 pure (Opt.Float float)
63 Opt.List <$> traverse optimizeExpr entries
66 do func <- Names.registerGlobal ModuleName.basics N.negate
67 arg <- optimizeExpr expr
68 pure $ Opt.Call func [arg]
70 Can.Binop _ home name _ left right ->
71 do optFunc <- Names.registerGlobal home name
72 optLeft <- optimizeExpr left
73 optRight <- optimizeExpr right
74 return (Opt.Call optFunc [optLeft, optRight])
76 Can.Lambda args body ->
77 do (argNames, defss) <- destructArgs args
78 obody <- optimizeExpr body
79 pure $ Opt.Function argNames (foldr Opt.Let obody (concat defss))
84 <*> traverse optimizeExpr args
86 Can.If branches finally ->
88 optimizeBranch (condition, branch) =
90 <$> optimizeExpr condition
91 <*> optimizeExpr branch
94 <$> traverse optimizeBranch branches
95 <*> optimizeExpr finally
98 optimizeDef def =<< optimizeExpr body
100 Can.LetRec defs body ->
104 <$> optimizePotentialTailCall def
105 <*> optimizeExpr body
108 do obody <- optimizeExpr body
109 foldM (\bod def -> optimizeDef def bod) obody defs
111 Can.LetDestruct pattern expr body ->
112 do (name, defs) <- destruct pattern
113 oexpr <- optimizeExpr expr
114 obody <- optimizeExpr body
116 Opt.Let (Opt.Def name oexpr) (foldr Opt.Let obody defs)
118 Can.Case expr branches ->
120 optimizeBranch root (Can.CaseBranch pattern branch) =
121 do defs <- destructHelp (Opt.VarLocal root) pattern []
122 obranch <- optimizeExpr branch
123 pure (pattern, foldr Opt.Let obranch defs)
125 do oexpr <- optimizeExpr expr
128 Case.optimize root <$> traverse (optimizeBranch root) branches
131 do root <- Names.generate
132 Case.optimize root <$> traverse (optimizeBranch root) branches
134 Can.Accessor field ->
135 pure (Opt.Accessor field)
137 Can.Access record field ->
138 do optRecord <- optimizeExpr record
139 pure (Opt.Access optRecord field)
141 Can.Update record updates ->
143 <$> optimizeExpr record
144 <*> traverse optimizeExpr updates
147 Opt.Record <$> traverse optimizeExpr fields
150 Names.registerKernel N.utils Opt.Unit
152 Can.Tuple a b maybeC ->
153 Names.registerKernel N.utils Opt.Tuple
156 <*> traverse optimizeExpr maybeC
158 Can.Shader _ src _ ->
159 pure (Opt.Shader src)
166optimizeDef :: Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
167optimizeDef def body =
169 Can.Def (A.At _ name) args expr ->
170 optimizeDefHelp name args expr body
172 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
173 optimizeDefHelp name (map fst typedArgs) expr body
176optimizeDefHelp :: N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
177optimizeDefHelp name args expr body =
180 do oexpr <- optimizeExpr expr
181 pure $ Opt.Let (Opt.Def name oexpr) body
184 do (argNames, defss) <- destructArgs args
185 let func = Opt.Function argNames (foldr Opt.Let body (concat defss))
187 Opt.Let (Opt.Def name func) body
194destructArgs :: [Can.Pattern] -> Names.Tracker ([N.Name], [[Opt.Def]])
196 unzip <$> traverse destruct args
199destruct :: Can.Pattern -> Names.Tracker (N.Name, [Opt.Def])
200destruct pattern@(A.At _ ptrn) =
205 Can.PAlias subPattern name ->
206 do revDefs <- destructHelp (Opt.VarLocal name) subPattern []
207 pure (name, reverse revDefs)
210 do name <- Names.generate
211 revDefs <- destructHelp (Opt.VarLocal name) pattern []
212 pure (name, reverse revDefs)
215destructHelp :: Opt.Expr -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
216destructHelp root (A.At region pattern) revDefs =
222 pure (Opt.Def name root : revDefs)
224 Can.PRecord fields ->
227 Opt.Def field (Opt.Access root field)
229 pure (map toDef fields ++ revDefs)
231 Can.PAlias subPattern name ->
232 destructHelp (Opt.VarLocal name) subPattern $
233 Opt.Def name root : revDefs
238 Can.PTuple a b maybeC ->
239 do name <- Names.generate
240 let tuple = Opt.VarLocal name
241 let newRevDefs = Opt.Def name root : revDefs
244 destructHelp (Opt.CtorAccess tuple Index.second) b =<<
245 destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
248 destructHelp (Opt.CtorAccess tuple Index.third) c =<<
249 destructHelp (Opt.CtorAccess tuple Index.second) b =<<
250 destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
256 destructCons root hd (A.At region (Can.PList tl)) revDefs
259 destructCons root hd tl revDefs
270 Can.PCtor _ _ _ _ _ args ->
271 do name <- Names.generate
273 (destructCtorArg (Opt.VarLocal name))
274 (Opt.Def name root : revDefs)
278destructCons :: Opt.Expr -> Can.Pattern -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
279destructCons root hd tl revDefs =
280 do name <- Names.generate
281 let list = Opt.VarLocal name
282 destructHelp (Opt.CtorAccess list Index.first) hd =<<
283 destructHelp (Opt.CtorAccess list Index.second) tl (Opt.Def name root : revDefs)
286destructCtorArg :: Opt.Expr -> [Opt.Def] -> Can.PatternCtorArg -> Names.Tracker [Opt.Def]
287destructCtorArg root revDefs (Can.PatternCtorArg index _ arg) =
288 destructHelp (Opt.CtorAccess root index) arg revDefs
295optimizePotentialTailCall :: Can.Def -> Names.Tracker Opt.Def
296optimizePotentialTailCall def =
298 Can.Def (A.At _ name) args expr ->
299 do (argNames, defss) <- destructArgs args
300 toTailDef name argNames defss <$>
301 optimizeTailExpr name argNames expr
303 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
304 do (argNames, defss) <- destructArgs (map fst typedArgs)
305 toTailDef name argNames defss <$>
306 optimizeTailExpr name argNames expr
309optimizeTailExpr :: N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
310optimizeTailExpr name argNames locExpr@(A.At _ expression) =
312 Can.Call (A.At _ (Can.VarTopLevel _ funcName)) args ->
313 if funcName == name && length args == length argNames then
314 Opt.TailCall name argNames <$> traverse optimizeExpr args
318 Can.If branches finally ->
320 optimizeBranch (condition, branch) =
322 <$> optimizeExpr condition
323 <*> optimizeTailExpr name argNames branch
326 <$> traverse optimizeBranch branches
327 <*> optimizeTailExpr name argNames finally
330 optimizeDef def =<< optimizeTailExpr name argNames body
332 Can.LetRec defs body ->
336 <$> optimizePotentialTailCall def
337 <*> optimizeTailExpr name argNames body
340 do obody <- optimizeTailExpr name argNames body
341 foldM (\bod def -> optimizeDef def bod) obody defs
343 Can.LetDestruct pattern expr body ->
344 do (dname, defs) <- destruct pattern
345 oexpr <- optimizeExpr expr
346 obody <- optimizeTailExpr dname argNames body
348 Opt.Let (Opt.Def dname oexpr) (foldr Opt.Let obody defs)
350 Can.Case expr branches ->
352 optimizeBranch root (Can.CaseBranch pattern branch) =
353 do defs <- destructHelp (Opt.VarLocal root) pattern []
354 obranch <- optimizeTailExpr name argNames branch
355 pure (pattern, foldr Opt.Let obranch defs)
357 do oexpr <- optimizeExpr expr
360 Case.optimize root <$> traverse (optimizeBranch root) branches
363 do root <- Names.generate
364 Case.optimize root <$> traverse (optimizeBranch root) branches
374toTailDef :: N.Name -> [N.Name] -> [[Opt.Def]] -> Opt.Expr -> Opt.Def
375toTailDef name argNames defss body =
376 if hasTailCall body then
377 Opt.TailDef name argNames (foldr Opt.Let body (concat defss))
379 Opt.Def name (Opt.Function argNames (foldr Opt.Let body (concat defss)))
382hasTailCall :: Opt.Expr -> Bool
383hasTailCall expression =
385 Opt.TailCall _ _ _ ->
388 Opt.If branches finally ->
389 hasTailCall finally || any (hasTailCall . snd) branches
394 Opt.Case _ _ branches ->
395 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