@@ -1,12 +1,17 @@
11{-# OPTIONS_GHC -Wall #-}
22{-# LANGUAGE OverloadedStrings #-}
3−module Optimize
4− ( optimizeExpr
3+module Optimize.Expression
4+ ( Cycle
5+ , optimize
6+ , destructArgs
7+ , optimizePotentialTailCall
58 )
69 where
710
811
12+import Prelude hiding (cycle)
913import Control.Monad (foldM)
14+import qualified Data.Set as Set
1015
1116import qualified AST.Canonical as Can
1217import qualified AST.Optimized as Opt
@@ -22,18 +27,21 @@ import qualified Reporting.Annotation as A
2227-- OPTIMIZE
2328
2429
30+type Cycle =
31+ Set.Set N.Name
2532
26−-- EXPRESSIONS
2733
28−
29−optimizeExpr :: Can.Expr -> Names.Tracker Opt.Expr
30−optimizeExpr (A.At region expression) =
34+optimize :: Cycle -> Can.Expr -> Names.Tracker Opt.Expr
35+optimize cycle (A.At region expression) =
3136 case expression of
3237 Can.VarLocal name ->
3338 pure (Opt.VarLocal name)
3439
3540 Can.VarTopLevel home name ->
36− Names.registerGlobal home name
41+ if Set.member name cycle then
42+ pure (Opt.VarCycle home name)
43+ else
44+ Names.registerGlobal home name
3745
3846 Can.VarKernel home name ->
3947 Names.registerKernel home (Opt.VarKernel home name)
@@ -60,58 +68,58 @@ optimizeExpr (A.At region expression) =
6068 pure (Opt.Float float)
6169
6270 Can.List entries ->
63− Opt.List <$> traverse optimizeExpr entries
71+ Opt.List <$> traverse (optimize cycle) entries
6472
6573 Can.Negate expr ->
6674 do func <- Names.registerGlobal ModuleName.basics N.negate
67− arg <- optimizeExpr expr
75+ arg <- optimize cycle expr
6876 pure $ Opt.Call func [arg]
6977
7078 Can.Binop _ home name _ left right ->
7179 do optFunc <- Names.registerGlobal home name
72− optLeft <- optimizeExpr left
73− optRight <- optimizeExpr right
80+ optLeft <- optimize cycle left
81+ optRight <- optimize cycle right
7482 return (Opt.Call optFunc [optLeft, optRight])
7583
7684 Can.Lambda args body ->
7785 do (argNames, defss) <- destructArgs args
78− obody <- optimizeExpr body
86+ obody <- optimize cycle body
7987 pure $ Opt.Function argNames (foldr Opt.Let obody (concat defss))
8088
8189 Can.Call func args ->
8290 Opt.Call
83− <$> optimizeExpr func
84− <*> traverse optimizeExpr args
91+ <$> optimize cycle func
92+ <*> traverse (optimize cycle) args
8593
8694 Can.If branches finally ->
8795 let
8896 optimizeBranch (condition, branch) =
8997 (,)
90− <$> optimizeExpr condition
91− <*> optimizeExpr branch
98+ <$> optimize cycle condition
99+ <*> optimize cycle branch
92100 in
93101 Opt.If
94102 <$> traverse optimizeBranch branches
95− <*> optimizeExpr finally
103+ <*> optimize cycle finally
96104
97105 Can.Let def body ->
98− optimizeDef def =<< optimizeExpr body
106+ optimizeDef cycle def =<< optimize cycle body
99107
100108 Can.LetRec defs body ->
101109 case defs of
102110 [def] ->
103111 Opt.Let
104− <$> optimizePotentialTailCall def
105− <*> optimizeExpr body
112+ <$> optimizePotentialTailCall cycle def
113+ <*> optimize cycle body
106114
107115 _ ->
108− do obody <- optimizeExpr body
109− foldM (\bod def -> optimizeDef def bod) obody defs
116+ do obody <- optimize cycle body
117+ foldM (\bod def -> optimizeDef cycle def bod) obody defs
110118
111119 Can.LetDestruct pattern expr body ->
112120 do (name, defs) <- destruct pattern
113− oexpr <- optimizeExpr expr
114− obody <- optimizeExpr body
121+ oexpr <- optimize cycle expr
122+ obody <- optimize cycle body
115123 pure $
116124 Opt.Let (Opt.Def name oexpr) (foldr Opt.Let obody defs)
117125
@@ -119,10 +127,10 @@ optimizeExpr (A.At region expression) =
119127 let
120128 optimizeBranch root (Can.CaseBranch pattern branch) =
121129 do defs <- destructHelp (Opt.VarLocal root) pattern []
122− obranch <- optimizeExpr branch
130+ obranch <- optimize cycle branch
123131 pure (pattern, foldr Opt.Let obranch defs)
124132 in
125− do oexpr <- optimizeExpr expr
133+ do oexpr <- optimize cycle expr
126134 case oexpr of
127135 Opt.VarLocal root ->
128136 Case.optimize root <$> traverse (optimizeBranch root) branches
@@ -135,26 +143,26 @@ optimizeExpr (A.At region expression) =
135143 Names.registerField field (Opt.Accessor field)
136144
137145 Can.Access record field ->
138− do optRecord <- optimizeExpr record
146+ do optRecord <- optimize cycle record
139147 Names.registerField field (Opt.Access optRecord field)
140148
141149 Can.Update record updates ->
142− Names.registerFields updates Opt.Update
143− <*> optimizeExpr record
144− <*> traverse optimizeExpr updates
150+ Names.registerFieldDict updates Opt.Update
151+ <*> optimize cycle record
152+ <*> traverse (optimize cycle) updates
145153
146154 Can.Record fields ->
147− Names.registerFields fields Opt.Record
148− <*> traverse optimizeExpr fields
155+ Names.registerFieldDict fields Opt.Record
156+ <*> traverse (optimize cycle) fields
149157
150158 Can.Unit ->
151159 Names.registerKernel N.utils Opt.Unit
152160
153161 Can.Tuple a b maybeC ->
154162 Names.registerKernel N.utils Opt.Tuple
155− <*> optimizeExpr a
156− <*> optimizeExpr b
157− <*> traverse optimizeExpr maybeC
163+ <*> optimize cycle a
164+ <*> optimize cycle b
165+ <*> traverse (optimize cycle) maybeC
158166
159167 Can.Shader _ src _ ->
160168 pure (Opt.Shader src)
@@ -164,28 +172,27 @@ optimizeExpr (A.At region expression) =
164172-- DEFINITION
165173
166174
167−optimizeDef :: Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
168−optimizeDef def body =
175+optimizeDef :: Cycle -> Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
176+optimizeDef cycle def body =
169177 case def of
170178 Can.Def (A.At _ name) args expr ->
171− optimizeDefHelp name args expr body
179+ optimizeDefHelp cycle name args expr body
172180
173181 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
174− optimizeDefHelp name (map fst typedArgs) expr body
182+ optimizeDefHelp cycle name (map fst typedArgs) expr body
175183
176184
177−optimizeDefHelp :: N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
178−optimizeDefHelp name args expr body =
185+optimizeDefHelp :: Cycle -> N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
186+optimizeDefHelp cycle name args expr body =
179187 case args of
180188 [] ->
181− do oexpr <- optimizeExpr expr
189+ do oexpr <- optimize cycle expr
182190 pure $ Opt.Let (Opt.Def name oexpr) body
183191
184192 _ ->
185193 do (argNames, defss) <- destructArgs args
186− let func = Opt.Function argNames (foldr Opt.Let body (concat defss))
187− pure $
188− Opt.Let (Opt.Def name func) body
194+ let oexpr = Opt.Function argNames (foldr Opt.Let body (concat defss))
195+ pure $ Opt.Let (Opt.Def name oexpr) body
189196
190197
191198
@@ -223,12 +230,8 @@ destructHelp root (A.At region pattern) revDefs =
223230 pure (Opt.Def name root : revDefs)
224231
225232 Can.PRecord fields ->
226− let
227− addFieldDef defs name =
228− Names.registerField name $
229− Opt.Def name (Opt.Access root name) : defs
230− in
231− foldM addFieldDef revDefs fields
233+ let toDef name = Opt.Def name (Opt.Access root name) in
234+ Names.registerFieldList fields (map toDef fields ++ revDefs)
232235
233236 Can.PAlias subPattern name ->
234237 destructHelp (Opt.VarLocal name) subPattern $
@@ -294,58 +297,58 @@ destructCtorArg root revDefs (Can.PatternCtorArg index _ arg) =
294297-- TAIL CALL
295298
296299
297−optimizePotentialTailCall :: Can.Def -> Names.Tracker Opt.Def
298−optimizePotentialTailCall def =
300+optimizePotentialTailCall :: Cycle -> Can.Def -> Names.Tracker Opt.Def
301+optimizePotentialTailCall cycle def =
299302 case def of
300303 Can.Def (A.At _ name) args expr ->
301304 do (argNames, defss) <- destructArgs args
302305 toTailDef name argNames defss <$>
303− optimizeTailExpr name argNames expr
306+ optimizeTail cycle name argNames expr
304307
305308 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
306309 do (argNames, defss) <- destructArgs (map fst typedArgs)
307310 toTailDef name argNames defss <$>
308− optimizeTailExpr name argNames expr
311+ optimizeTail cycle name argNames expr
309312
310313
311−optimizeTailExpr :: N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
312−optimizeTailExpr name argNames locExpr@(A.At _ expression) =
314+optimizeTail :: Cycle -> N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
315+optimizeTail cycle name argNames locExpr@(A.At _ expression) =
313316 case expression of
314317 Can.Call (A.At _ (Can.VarTopLevel _ funcName)) args ->
315318 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
317320 else
318− optimizeExpr locExpr
321+ optimize cycle locExpr
319322
320323 Can.If branches finally ->
321324 let
322325 optimizeBranch (condition, branch) =
323326 (,)
324− <$> optimizeExpr condition
325− <*> optimizeTailExpr name argNames branch
327+ <$> optimize cycle condition
328+ <*> optimizeTail cycle name argNames branch
326329 in
327330 Opt.If
328331 <$> traverse optimizeBranch branches
329− <*> optimizeTailExpr name argNames finally
332+ <*> optimizeTail cycle name argNames finally
330333
331334 Can.Let def body ->
332− optimizeDef def =<< optimizeTailExpr name argNames body
335+ optimizeDef cycle def =<< optimizeTail cycle name argNames body
333336
334337 Can.LetRec defs body ->
335338 case defs of
336339 [def] ->
337340 Opt.Let
338− <$> optimizePotentialTailCall def
339− <*> optimizeTailExpr name argNames body
341+ <$> optimizePotentialTailCall cycle def
342+ <*> optimizeTail cycle name argNames body
340343
341344 _ ->
342− do obody <- optimizeTailExpr name argNames body
343− foldM (\bod def -> optimizeDef def bod) obody defs
345+ do obody <- optimizeTail cycle name argNames body
346+ foldM (\bod def -> optimizeDef cycle def bod) obody defs
344347
345348 Can.LetDestruct pattern expr body ->
346349 do (dname, defs) <- destruct pattern
347− oexpr <- optimizeExpr expr
348− obody <- optimizeTailExpr dname argNames body
350+ oexpr <- optimize cycle expr
351+ obody <- optimizeTail cycle dname argNames body
349352 pure $
350353 Opt.Let (Opt.Def dname oexpr) (foldr Opt.Let obody defs)
351354
@@ -353,10 +356,10 @@ optimizeTailExpr name argNames locExpr@(A.At _ expression) =
353356 let
354357 optimizeBranch root (Can.CaseBranch pattern branch) =
355358 do defs <- destructHelp (Opt.VarLocal root) pattern []
356− obranch <- optimizeTailExpr name argNames branch
359+ obranch <- optimizeTail cycle name argNames branch
357360 pure (pattern, foldr Opt.Let obranch defs)
358361 in
359− do oexpr <- optimizeExpr expr
362+ do oexpr <- optimize cycle expr
360363 case oexpr of
361364 Opt.VarLocal root ->
362365 Case.optimize root <$> traverse (optimizeBranch root) branches
@@ -366,7 +369,7 @@ optimizeTailExpr name argNames locExpr@(A.At _ expression) =
366369 Case.optimize root <$> traverse (optimizeBranch root) branches
367370
368371 _ ->
369− optimizeExpr locExpr
372+ optimize cycle locExpr
370373
371374
372375