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 Names.registerField field (Opt.Accessor field)
137 Can.Access record field ->
138 do optRecord <- optimizeExpr record
139 Names.registerField field (Opt.Access optRecord field)
141 Can.Update record updates ->
142 Names.registerFields updates Opt.Update
143 <*> optimizeExpr record
144 <*> traverse optimizeExpr updates
147 Names.registerFields fields Opt.Record
148 <*> traverse optimizeExpr fields
151 Names.registerKernel N.utils Opt.Unit
153 Can.Tuple a b maybeC ->
154 Names.registerKernel N.utils Opt.Tuple
157 <*> traverse optimizeExpr maybeC
159 Can.Shader _ src _ ->
160 pure (Opt.Shader src)
167optimizeDef :: Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
168optimizeDef def body =
170 Can.Def (A.At _ name) args expr ->
171 optimizeDefHelp name args expr body
173 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
174 optimizeDefHelp name (map fst typedArgs) expr body
177optimizeDefHelp :: N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
178optimizeDefHelp name args expr body =
181 do oexpr <- optimizeExpr expr
182 pure $ Opt.Let (Opt.Def name oexpr) body
185 do (argNames, defss) <- destructArgs args
186 let func = Opt.Function argNames (foldr Opt.Let body (concat defss))
188 Opt.Let (Opt.Def name func) body
195destructArgs :: [Can.Pattern] -> Names.Tracker ([N.Name], [[Opt.Def]])
197 unzip <$> traverse destruct args
200destruct :: Can.Pattern -> Names.Tracker (N.Name, [Opt.Def])
201destruct pattern@(A.At _ ptrn) =
206 Can.PAlias subPattern name ->
207 do revDefs <- destructHelp (Opt.VarLocal name) subPattern []
208 pure (name, reverse revDefs)
211 do name <- Names.generate
212 revDefs <- destructHelp (Opt.VarLocal name) pattern []
213 pure (name, reverse revDefs)
216destructHelp :: Opt.Expr -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
217destructHelp root (A.At region pattern) revDefs =
223 pure (Opt.Def name root : revDefs)
225 Can.PRecord fields ->
227 addFieldDef defs name =
228 Names.registerField name $
229 Opt.Def name (Opt.Access root name) : defs
231 foldM addFieldDef revDefs fields
233 Can.PAlias subPattern name ->
234 destructHelp (Opt.VarLocal name) subPattern $
235 Opt.Def name root : revDefs
240 Can.PTuple a b maybeC ->
241 do name <- Names.generate
242 let tuple = Opt.VarLocal name
243 let newRevDefs = Opt.Def name root : revDefs
246 destructHelp (Opt.CtorAccess tuple Index.second) b =<<
247 destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
250 destructHelp (Opt.CtorAccess tuple Index.third) c =<<
251 destructHelp (Opt.CtorAccess tuple Index.second) b =<<
252 destructHelp (Opt.CtorAccess tuple Index.first) a newRevDefs
258 destructCons root hd (A.At region (Can.PList tl)) revDefs
261 destructCons root hd tl revDefs
272 Can.PCtor _ _ _ _ _ args ->
273 do name <- Names.generate
275 (destructCtorArg (Opt.VarLocal name))
276 (Opt.Def name root : revDefs)
280destructCons :: Opt.Expr -> Can.Pattern -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
281destructCons root hd tl revDefs =
282 do name <- Names.generate
283 let list = Opt.VarLocal name
284 destructHelp (Opt.CtorAccess list Index.first) hd =<<
285 destructHelp (Opt.CtorAccess list Index.second) tl (Opt.Def name root : revDefs)
288destructCtorArg :: Opt.Expr -> [Opt.Def] -> Can.PatternCtorArg -> Names.Tracker [Opt.Def]
289destructCtorArg root revDefs (Can.PatternCtorArg index _ arg) =
290 destructHelp (Opt.CtorAccess root index) arg revDefs
297optimizePotentialTailCall :: Can.Def -> Names.Tracker Opt.Def
298optimizePotentialTailCall def =
300 Can.Def (A.At _ name) args expr ->
301 do (argNames, defss) <- destructArgs args
302 toTailDef name argNames defss <$>
303 optimizeTailExpr name argNames expr
305 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
306 do (argNames, defss) <- destructArgs (map fst typedArgs)
307 toTailDef name argNames defss <$>
308 optimizeTailExpr name argNames expr
311optimizeTailExpr :: N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
312optimizeTailExpr name argNames locExpr@(A.At _ expression) =
314 Can.Call (A.At _ (Can.VarTopLevel _ funcName)) args ->
315 if funcName == name && length args == length argNames then
316 Opt.TailCall name argNames <$> traverse optimizeExpr args
320 Can.If branches finally ->
322 optimizeBranch (condition, branch) =
324 <$> optimizeExpr condition
325 <*> optimizeTailExpr name argNames branch
328 <$> traverse optimizeBranch branches
329 <*> optimizeTailExpr name argNames finally
332 optimizeDef def =<< optimizeTailExpr name argNames body
334 Can.LetRec defs body ->
338 <$> optimizePotentialTailCall def
339 <*> optimizeTailExpr name argNames body
342 do obody <- optimizeTailExpr name argNames body
343 foldM (\bod def -> optimizeDef def bod) obody defs
345 Can.LetDestruct pattern expr body ->
346 do (dname, defs) <- destruct pattern
347 oexpr <- optimizeExpr expr
348 obody <- optimizeTailExpr dname argNames body
350 Opt.Let (Opt.Def dname oexpr) (foldr Opt.Let obody defs)
352 Can.Case expr branches ->
354 optimizeBranch root (Can.CaseBranch pattern branch) =
355 do defs <- destructHelp (Opt.VarLocal root) pattern []
356 obranch <- optimizeTailExpr name argNames branch
357 pure (pattern, foldr Opt.Let obranch defs)
359 do oexpr <- optimizeExpr expr
362 Case.optimize root <$> traverse (optimizeBranch root) branches
365 do root <- Names.generate
366 Case.optimize root <$> traverse (optimizeBranch root) branches
376toTailDef :: N.Name -> [N.Name] -> [[Opt.Def]] -> Opt.Expr -> Opt.Def
377toTailDef name argNames defss body =
378 if hasTailCall body then
379 Opt.TailDef name argNames (foldr Opt.Let body (concat defss))
381 Opt.Def name (Opt.Function argNames (foldr Opt.Let body (concat defss)))
384hasTailCall :: Opt.Expr -> Bool
385hasTailCall expression =
387 Opt.TailCall _ _ _ ->
390 Opt.If branches finally ->
391 hasTailCall finally || any (hasTailCall . snd) branches
396 Opt.Case _ _ branches ->
397 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