@@ -1,12 +1,17 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−module Optimize
3+module Optimize.Expression
4− ( optimizeExpr
4+ ( Cycle
7+ , optimizePotentialTailCall
12+import Prelude hiding (cycle)
9import Control.Monad (foldM)
13import Control.Monad (foldM)
14+import qualified Data.Set as Set
11import qualified AST.Canonical as Can
16import qualified AST.Canonical as Can
12import qualified AST.Optimized as Opt
17import qualified AST.Optimized as Opt
@@ -22,18 +27,21 @@ import qualified Reporting.Annotation as A
22-- OPTIMIZE
27-- OPTIMIZE
29−optimizeExpr :: Can.Expr -> Names.Tracker Opt.Expr
34+optimize :: Cycle -> Can.Expr -> Names.Tracker Opt.Expr
30−optimizeExpr (A.At region expression) =
35+optimize cycle (A.At region expression) =
31 case expression of
36 case expression of
32 Can.VarLocal name ->
37 Can.VarLocal name ->
33 pure (Opt.VarLocal name)
38 pure (Opt.VarLocal name)
35 Can.VarTopLevel home name ->
40 Can.VarTopLevel home name ->
41+ if Set.member name cycle then
42+ pure (Opt.VarCycle home name)
36− Names.registerGlobal home name
44+ Names.registerGlobal home name
38 Can.VarKernel home name ->
46 Can.VarKernel home name ->
39 Names.registerKernel home (Opt.VarKernel home name)
47 Names.registerKernel home (Opt.VarKernel home name)
@@ -60,58 +68,58 @@ optimizeExpr (A.At region expression) =
60 pure (Opt.Float float)
68 pure (Opt.Float float)
62 Can.List entries ->
70 Can.List entries ->
63− Opt.List <$> traverse optimizeExpr entries
71+ Opt.List <$> traverse (optimize cycle) entries
65 Can.Negate expr ->
73 Can.Negate expr ->
66 do func <- Names.registerGlobal ModuleName.basics N.negate
74 do func <- Names.registerGlobal ModuleName.basics N.negate
67− arg <- optimizeExpr expr
75+ arg <- optimize cycle expr
68 pure $ Opt.Call func [arg]
76 pure $ Opt.Call func [arg]
70 Can.Binop _ home name _ left right ->
78 Can.Binop _ home name _ left right ->
71 do optFunc <- Names.registerGlobal home name
79 do optFunc <- Names.registerGlobal home name
72− optLeft <- optimizeExpr left
80+ optLeft <- optimize cycle left
73− optRight <- optimizeExpr right
81+ optRight <- optimize cycle right
74 return (Opt.Call optFunc [optLeft, optRight])
82 return (Opt.Call optFunc [optLeft, optRight])
76 Can.Lambda args body ->
84 Can.Lambda args body ->
77 do (argNames, defss) <- destructArgs args
85 do (argNames, defss) <- destructArgs args
78− obody <- optimizeExpr body
86+ obody <- optimize cycle body
79 pure $ Opt.Function argNames (foldr Opt.Let obody (concat defss))
87 pure $ Opt.Function argNames (foldr Opt.Let obody (concat defss))
81 Can.Call func args ->
89 Can.Call func args ->
83− <$> optimizeExpr func
91+ <$> optimize cycle func
84− <*> traverse optimizeExpr args
92+ <*> traverse (optimize cycle) args
86 Can.If branches finally ->
94 Can.If branches finally ->
88 optimizeBranch (condition, branch) =
96 optimizeBranch (condition, branch) =
90− <$> optimizeExpr condition
98+ <$> optimize cycle condition
91− <*> optimizeExpr branch
99+ <*> optimize cycle branch
94 <$> traverse optimizeBranch branches
102 <$> traverse optimizeBranch branches
95− <*> optimizeExpr finally
103+ <*> optimize cycle finally
97 Can.Let def body ->
105 Can.Let def body ->
98− optimizeDef def =<< optimizeExpr body
106+ optimizeDef cycle def =<< optimize cycle body
100 Can.LetRec defs body ->
108 Can.LetRec defs body ->
101 case defs of
109 case defs of
104− <$> optimizePotentialTailCall def
112+ <$> optimizePotentialTailCall cycle def
105− <*> optimizeExpr body
113+ <*> optimize cycle body
108− do obody <- optimizeExpr body
116+ do obody <- optimize cycle body
109− foldM (\bod def -> optimizeDef def bod) obody defs
117+ foldM (\bod def -> optimizeDef cycle def bod) obody defs
111 Can.LetDestruct pattern expr body ->
119 Can.LetDestruct pattern expr body ->
112 do (name, defs) <- destruct pattern
120 do (name, defs) <- destruct pattern
113− oexpr <- optimizeExpr expr
121+ oexpr <- optimize cycle expr
114− obody <- optimizeExpr body
122+ obody <- optimize cycle body
116 Opt.Let (Opt.Def name oexpr) (foldr Opt.Let obody defs)
124 Opt.Let (Opt.Def name oexpr) (foldr Opt.Let obody defs)
@@ -119,10 +127,10 @@ optimizeExpr (A.At region expression) =
120 optimizeBranch root (Can.CaseBranch pattern branch) =
128 optimizeBranch root (Can.CaseBranch pattern branch) =
121 do defs <- destructHelp (Opt.VarLocal root) pattern []
129 do defs <- destructHelp (Opt.VarLocal root) pattern []
122− obranch <- optimizeExpr branch
130+ obranch <- optimize cycle branch
123 pure (pattern, foldr Opt.Let obranch defs)
131 pure (pattern, foldr Opt.Let obranch defs)
125− do oexpr <- optimizeExpr expr
133+ do oexpr <- optimize cycle expr
126 case oexpr of
134 case oexpr of
127 Opt.VarLocal root ->
135 Opt.VarLocal root ->
128 Case.optimize root <$> traverse (optimizeBranch root) branches
136 Case.optimize root <$> traverse (optimizeBranch root) branches
@@ -135,26 +143,26 @@ optimizeExpr (A.At region expression) =
135 Names.registerField field (Opt.Accessor field)
143 Names.registerField field (Opt.Accessor field)
137 Can.Access record field ->
145 Can.Access record field ->
138− do optRecord <- optimizeExpr record
146+ do optRecord <- optimize cycle record
139 Names.registerField field (Opt.Access optRecord field)
147 Names.registerField field (Opt.Access optRecord field)
141 Can.Update record updates ->
149 Can.Update record updates ->
142− Names.registerFields updates Opt.Update
150+ Names.registerFieldDict updates Opt.Update
143− <*> optimizeExpr record
151+ <*> optimize cycle record
144− <*> traverse optimizeExpr updates
152+ <*> traverse (optimize cycle) updates
146 Can.Record fields ->
154 Can.Record fields ->
147− Names.registerFields fields Opt.Record
155+ Names.registerFieldDict fields Opt.Record
148− <*> traverse optimizeExpr fields
156+ <*> traverse (optimize cycle) fields
150 Can.Unit ->
158 Can.Unit ->
151 Names.registerKernel N.utils Opt.Unit
159 Names.registerKernel N.utils Opt.Unit
153 Can.Tuple a b maybeC ->
161 Can.Tuple a b maybeC ->
154 Names.registerKernel N.utils Opt.Tuple
162 Names.registerKernel N.utils Opt.Tuple
155− <*> optimizeExpr a
163+ <*> optimize cycle a
156− <*> optimizeExpr b
164+ <*> optimize cycle b
157− <*> traverse optimizeExpr maybeC
165+ <*> traverse (optimize cycle) maybeC
159 Can.Shader _ src _ ->
167 Can.Shader _ src _ ->
160 pure (Opt.Shader src)
168 pure (Opt.Shader src)
@@ -164,28 +172,27 @@ optimizeExpr (A.At region expression) =
164-- DEFINITION
172-- DEFINITION
167−optimizeDef :: Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
175+optimizeDef :: Cycle -> Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
168−optimizeDef def body =
176+optimizeDef cycle def body =
169 case def of
177 case def of
170 Can.Def (A.At _ name) args expr ->
178 Can.Def (A.At _ name) args expr ->
171− optimizeDefHelp name args expr body
179+ optimizeDefHelp cycle name args expr body
173 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
181 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
174− optimizeDefHelp name (map fst typedArgs) expr body
182+ optimizeDefHelp cycle name (map fst typedArgs) expr body
177−optimizeDefHelp :: N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
185+optimizeDefHelp :: Cycle -> N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
178−optimizeDefHelp name args expr body =
186+optimizeDefHelp cycle name args expr body =
179 case args of
187 case args of
181− do oexpr <- optimizeExpr expr
189+ do oexpr <- optimize cycle expr
182 pure $ Opt.Let (Opt.Def name oexpr) body
190 pure $ Opt.Let (Opt.Def name oexpr) body
185 do (argNames, defss) <- destructArgs args
193 do (argNames, defss) <- destructArgs args
186− let func = Opt.Function argNames (foldr Opt.Let body (concat defss))
194+ let oexpr = Opt.Function argNames (foldr Opt.Let body (concat defss))
188− Opt.Let (Opt.Def name func) body
195+ pure $ Opt.Let (Opt.Def name oexpr) body
@@ -223,12 +230,8 @@ destructHelp root (A.At region pattern) revDefs =
223 pure (Opt.Def name root : revDefs)
230 pure (Opt.Def name root : revDefs)
225 Can.PRecord fields ->
232 Can.PRecord fields ->
227− addFieldDef defs name =
228− Names.registerField name $
229− Opt.Def name (Opt.Access root name) : defs
233+ let toDef name = Opt.Def name (Opt.Access root name) in
230− in
234+ Names.registerFieldList fields (map toDef fields ++ revDefs)
231− foldM addFieldDef revDefs fields
233 Can.PAlias subPattern name ->
236 Can.PAlias subPattern name ->
234 destructHelp (Opt.VarLocal name) subPattern $
237 destructHelp (Opt.VarLocal name) subPattern $
@@ -294,58 +297,58 @@ destructCtorArg root revDefs (Can.PatternCtorArg index _ arg) =
294-- TAIL CALL
297-- TAIL CALL
297−optimizePotentialTailCall :: Can.Def -> Names.Tracker Opt.Def
300+optimizePotentialTailCall :: Cycle -> Can.Def -> Names.Tracker Opt.Def
298−optimizePotentialTailCall def =
301+optimizePotentialTailCall cycle def =
299 case def of
302 case def of
300 Can.Def (A.At _ name) args expr ->
303 Can.Def (A.At _ name) args expr ->
301 do (argNames, defss) <- destructArgs args
304 do (argNames, defss) <- destructArgs args
302 toTailDef name argNames defss <$>
305 toTailDef name argNames defss <$>
303− optimizeTailExpr name argNames expr
306+ optimizeTail cycle name argNames expr
305 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
308 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
306 do (argNames, defss) <- destructArgs (map fst typedArgs)
309 do (argNames, defss) <- destructArgs (map fst typedArgs)
307 toTailDef name argNames defss <$>
310 toTailDef name argNames defss <$>
308− optimizeTailExpr name argNames expr
311+ optimizeTail cycle name argNames expr
311−optimizeTailExpr :: N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
314+optimizeTail :: Cycle -> N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
312−optimizeTailExpr name argNames locExpr@(A.At _ expression) =
315+optimizeTail cycle name argNames locExpr@(A.At _ expression) =
313 case expression of
316 case expression of
314 Can.Call (A.At _ (Can.VarTopLevel _ funcName)) args ->
317 Can.Call (A.At _ (Can.VarTopLevel _ funcName)) args ->
315 if funcName == name && length args == length argNames then
318 if funcName == name && length args == length argNames then
316− Opt.TailCall name argNames <$> traverse optimizeExpr args
319+ Opt.TailCall name argNames <$> traverse (optimize cycle) args
318− optimizeExpr locExpr
321+ optimize cycle locExpr
320 Can.If branches finally ->
323 Can.If branches finally ->
322 optimizeBranch (condition, branch) =
325 optimizeBranch (condition, branch) =
324− <$> optimizeExpr condition
327+ <$> optimize cycle condition
325− <*> optimizeTailExpr name argNames branch
328+ <*> optimizeTail cycle name argNames branch
328 <$> traverse optimizeBranch branches
331 <$> traverse optimizeBranch branches
329− <*> optimizeTailExpr name argNames finally
332+ <*> optimizeTail cycle name argNames finally
331 Can.Let def body ->
334 Can.Let def body ->
332− optimizeDef def =<< optimizeTailExpr name argNames body
335+ optimizeDef cycle def =<< optimizeTail cycle name argNames body
334 Can.LetRec defs body ->
337 Can.LetRec defs body ->
335 case defs of
338 case defs of
338− <$> optimizePotentialTailCall def
341+ <$> optimizePotentialTailCall cycle def
339− <*> optimizeTailExpr name argNames body
342+ <*> optimizeTail cycle name argNames body
342− do obody <- optimizeTailExpr name argNames body
345+ do obody <- optimizeTail cycle name argNames body
343− foldM (\bod def -> optimizeDef def bod) obody defs
346+ foldM (\bod def -> optimizeDef cycle def bod) obody defs
345 Can.LetDestruct pattern expr body ->
348 Can.LetDestruct pattern expr body ->
346 do (dname, defs) <- destruct pattern
349 do (dname, defs) <- destruct pattern
347− oexpr <- optimizeExpr expr
350+ oexpr <- optimize cycle expr
348− obody <- optimizeTailExpr dname argNames body
351+ obody <- optimizeTail cycle dname argNames body
350 Opt.Let (Opt.Def dname oexpr) (foldr Opt.Let obody defs)
353 Opt.Let (Opt.Def dname oexpr) (foldr Opt.Let obody defs)
@@ -353,10 +356,10 @@ optimizeTailExpr name argNames locExpr@(A.At _ expression) =
354 optimizeBranch root (Can.CaseBranch pattern branch) =
357 optimizeBranch root (Can.CaseBranch pattern branch) =
355 do defs <- destructHelp (Opt.VarLocal root) pattern []
358 do defs <- destructHelp (Opt.VarLocal root) pattern []
356− obranch <- optimizeTailExpr name argNames branch
359+ obranch <- optimizeTail cycle name argNames branch
357 pure (pattern, foldr Opt.Let obranch defs)
360 pure (pattern, foldr Opt.Let obranch defs)
359− do oexpr <- optimizeExpr expr
362+ do oexpr <- optimize cycle expr
360 case oexpr of
363 case oexpr of
361 Opt.VarLocal root ->
364 Opt.VarLocal root ->
362 Case.optimize root <$> traverse (optimizeBranch root) branches
365 Case.optimize root <$> traverse (optimizeBranch root) branches
@@ -366,7 +369,7 @@ optimizeTailExpr name argNames locExpr@(A.At _ expression) =
366 Case.optimize root <$> traverse (optimizeBranch root) branches
369 Case.optimize root <$> traverse (optimizeBranch root) branches
369− optimizeExpr locExpr
372+ optimize cycle locExpr