@@ -1,25 +1,23 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−module Optimize (optimize) where
3+module Optimize
5−import Control.Arrow (second)
5+ )
6−import qualified Control.Monad as M
9+import Control.Monad (foldM)
7−import Data.Monoid ((<>))
10+
8−import qualified Data.Map as Map
9−import qualified Data.Set as Set
10−import qualified Data.Text as Text
11−import Data.Text (Text)
13−import qualified AST.Expression.Canonical as Can
11+import qualified AST.Canonical as Can
14−import qualified AST.Expression.Optimized as Opt
12+import qualified AST.Optimized as Opt
15import qualified AST.Module.Name as ModuleName
13import qualified AST.Module.Name as ModuleName
16−import qualified AST.Pattern as P
14+import qualified Data.Index as Index
17−import qualified AST.Variable as Var
15+import qualified Elm.Name as N
18−import qualified Optimize.Case as Case
16+--import qualified Optimize.Case as Case
19import qualified Optimize.DecisionTree as DT
17import qualified Optimize.DecisionTree as DT
20−import qualified Optimize.Environment as Env
18+import qualified Optimize.Names as Names
21−import qualified Optimize.Inline as Inline
19+--import qualified Optimize.Inline as Inline
22−import qualified Optimize.Port as Port
20+--import qualified Optimize.Port as Port
23import qualified Reporting.Annotation as A
21import qualified Reporting.Annotation as A
24import qualified Reporting.Region as R
22import qualified Reporting.Region as R
@@ -28,543 +26,353 @@ import qualified Reporting.Region as R
28-- OPTIMIZE
26-- OPTIMIZE
31−optimize :: DT.VariantDict -> ModuleName.Canonical -> [Can.Def] -> [(Text, Opt.Decl)]
32−optimize variantDict home defs =
33− concat $ zipWith (optimizeDecl variantDict home) [1 .. length defs] defs
40−optimizeDecl :: DT.VariantDict -> ModuleName.Canonical -> Int -> Can.Def -> [(Text, Opt.Decl)]
41−optimizeDecl variantDict home index (Can.Def _ pattern@(A.A _ ptrn) expression _) =
44− Can.collectLambdas expression
46− case (ptrn, rawArgs) of
48− (:[]) $ Env.run variantDict home $
49− optimizeNamedDef name rawArgs rawBody
53− name = "_" <> Text.pack (show index)
54− var = Var.Global home name
55− deps = Set.singleton var
57− Env.run variantDict home $
58− ((,) name . Opt.Def) <$> optimizeExpr Nothing rawBody
60− destruct (Opt.VarGlobal var) pattern
62− decl : map (second (Opt.Decl deps Set.empty Nothing)) destructors
65− error "bug manifesting in Optimize.optimizeDecl, please report"
72−optimizeLetDef :: Can.Def -> Env.Optimizer [(Text, Opt.Def)]
73−optimizeLetDef (Can.Def _ pattern@(A.A _ ptrn) expression _) =
76− Can.collectLambdas expression
78− case (ptrn, rawArgs) of
80− do def <- optimizeNamedDef name rawArgs rawBody
84− do name <- Env.freshName
85− body <- optimizeExpr Nothing rawBody
86− return $ (name, Opt.Def body) : destruct (Opt.VarLocal name) pattern
89− error "bug manifesting in Optimize.optimizeLetDef, please report"
92−optimizeNamedDef :: Text -> [P.Canonical] -> Can.Expr -> Env.Optimizer (Text, Opt.Def)
93−optimizeNamedDef name rawArgs rawBody =
96− do hasTailCall <- Env.getTailCall
97− body <- optimizeExpr Nothing rawBody
98− Env.setTailCall hasTailCall
99− return (name, Opt.Def body)
102− do htc <- Env.getTailCall
103− Env.setTailCall False
105− (args, body) <- optimizeFunction (Just name) rawArgs rawBody
30+-- EXPRESSIONS
107− isTailCall <- Env.getTailCall
112− Opt.TailDef args body
114− Opt.Def (Opt.Function args body)
117−destruct :: Opt.Expr -> P.Canonical -> [(Text, Opt.Def)]
118−destruct root pattern =
119− map (second Opt.Def) $
120− patternToSubstitutions root pattern
131− -> Env.Optimizer ([Text], Opt.Expr)
132−optimizeFunction maybeName patterns givenBody =
134− do (argNames, body) <- M.foldM depatternArgs ([], givenBody) (reverse patterns)
135− optBody <- optimizeExpr (makeContext argNames =<< maybeName) body
136− return (argNames, optBody)
139−makeContext :: [Text] -> Text -> Context
140−makeContext argNames name =
141− Just (name, length argNames, argNames)
144−depatternArgs :: ([Text], Can.Expr) -> P.Canonical -> Env.Optimizer ([Text], Can.Expr)
145−depatternArgs (names, rawExpr) ptrn =
146− do (name, expr) <- depattern ptrn rawExpr
147− return (name : names, expr)
151−-- TURN A PATTERN INTO A BUNCH OF SUBSTITUTIONS
33+optimizeExpr :: Can.Expr -> Names.Tracker Opt.Expr
34+optimizeExpr (A.At region expression) =
37+ pure (Opt.VarLocal name)
154−patternToSubstitutions :: Opt.Expr -> P.Canonical -> [(Text, Opt.Expr)]
39+ Can.VarTopLevel home name ->
155−patternToSubstitutions expr (A.A _ pattern) =
40+ Names.registerGlobal home name
160− P.Literal _ ->
42+ Can.VarKernel home name ->
161− []
43+ Names.registerKernel home (Opt.VarKernel home name)
163− P.Record fields ->
45+ Can.VarForeign home name _ ->
164− map (\name -> (name, Opt.Access expr name)) fields
46+ Names.registerGlobal home name
166− P.Anything ->
48+ Can.VarDebug home name _ ->
167− []
49+ Names.registerKernel N.debug (Opt.VarDebug name home region Nothing)
169− P.Alias alias realPattern ->
51+ Can.VarOperator _ home name _ ->
170− (alias, expr) : patternToSubstitutions expr realPattern
52+ Names.registerGlobal home name
172− P.Ctor _ patterns ->
54+ Can.Chr chr ->
173− concat (zipWith (patternToSubstitutions . Opt.CtorAccess expr) [0..] patterns)
55+ pure (Opt.Chr chr)
177−-- OPTIMIZE EXPRESSIONS
63+ Can.Float float ->
64+ pure (Opt.Float float)
67+ Opt.List <$> traverse optimizeExpr entries
180−type Context = Maybe (Text, Int, [Text])
69+ Can.Negate expr ->
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])
183−{-| This optimizer detects tail calls. The `Context` holds a function name,
80+ Can.Lambda args body ->
184−function arity, and list of argument names. If a tail call is possible, the
81+ do (argNames, defss) <- destructArgs args
185−`Context` will be filled in and we check any function we run into. If we go
82+ obody <- optimizeExpr body
186−down a route that cannot possibly have tail calls, we remove the context.
83+ pure $
187−-}
84+ Opt.Function argNames (foldr Opt.Let obody (concat defss))
188−optimizeExpr :: Context -> Can.Expr -> Env.Optimizer Opt.Expr
189−optimizeExpr context annExpr@(A.A region expression) =
192− optimizeExpr context
193− -- this *might* find a tail call, use this when something is a potential
196− justConvert =
86+ Can.Call func args ->
197− optimizeExpr Nothing
198− -- this will never find tail calls, use this when you are working with
199− -- expressions that cannot be turned into tail calls
203− pure (Opt.Literal lit)
206− optimizeVariable region var
208− Can.List elements ->
209− Opt.List
87+ Opt.Call
210− <$> traverse justConvert elements
88+ <$> optimizeExpr func
212− Can.Binop op leftExpr rightExpr ->
213− optimizeBinop context region op leftExpr rightExpr
218− Can.collectLambdas annExpr
220− uncurry Opt.Function <$> optimizeFunction Nothing patterns body
225− Can.collectApps annExpr
227− case getTailCallInfo context func (length args) of
228− Just (name, argNames) ->
229− do optArgs <- traverse justConvert args
230− Env.setTailCall True
231− return (Opt.TailCall name argNames optArgs)
234− do hasTailCall <- Env.getTailCall
235− optFunc <- justConvert func
236− optArgs <- traverse justConvert args
89+ <*> traverse optimizeExpr args
237− Env.setTailCall hasTailCall
238− return (Opt.Call optFunc optArgs)
240 Can.If branches finally ->
91 Can.If branches finally ->
242− crawlBranch (cond,branch) =
93+ optimizeBranch (condition, branch) =
243− (,) <$> justConvert cond <*> keepLooking branch
94+ (,)
95+ <$> optimizeExpr condition
96+ <*> optimizeExpr branch
246− <$> traverse crawlBranch branches
99+ <$> traverse optimizeBranch branches
247− <*> keepLooking finally
100+ <*> optimizeExpr finally
103+ optimizeDef def =<< optimizeExpr body
249− Can.Let defs body ->
105+ Can.LetRec defs body ->
250− do optDefs <- concat <$> traverse optimizeLetDef defs
106+ case defs of
251− Opt.Let optDefs <$> keepLooking body
107+ [def] ->
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)
253 Can.Case expr branches ->
123 Can.Case expr branches ->
254− do optExpr <- optimizeExpr Nothing expr
124+ error "TODO"
255− variantDict <- Env.getVariantDict
257− name <- Env.freshName
258− optBranches <- traverse (optimizeBranch context region name) branches
259− let optCase = Case.optimize variantDict name optBranches
260− return $ Opt.Let [ (name, Opt.Def optExpr) ] optCase
262− Can.Ctor (Var.Canonical _ name) exprs ->
126+ Can.Accessor field ->
263− Opt.Ctor name <$> traverse justConvert exprs
127+ pure (Opt.Accessor field)
265 Can.Access record field ->
129 Can.Access record field ->
130+ do optRecord <- optimizeExpr record
266− Opt.Access
131+ pure (Opt.Access optRecord field)
267− <$> justConvert record
270− Can.Update record fields ->
133+ Can.Update record updates ->
271− Opt.Update
134+ Opt.Update
272− <$> justConvert record
135+ <$> optimizeExpr record
273− <*> traverse (traverse justConvert) fields
136+ <*> traverse optimizeExpr updates
275 Can.Record fields ->
138 Can.Record fields ->
277− <$> traverse (traverse justConvert) fields
139+ Opt.Record <$> traverse optimizeExpr fields
279− Can.Cmd home manager ->
141+ Can.Unit ->
280− Opt.Cmd home <$> Env.registerEffects home manager
142+ Names.registerKernel N.utils Opt.Unit
282− Can.Sub home manager ->
144+ Can.Tuple a b maybeC ->
283− Opt.Sub home <$> Env.registerEffects home manager
145+ Names.registerKernel N.utils Opt.Tuple
148+ <*> traverse optimizeExpr maybeC
285− Can.OutgoingPort name tipe ->
150+ Can.Shader _ src _ ->
286− Opt.OutgoingPort name <$> Port.toEncoder tipe
151+ pure (Opt.Shader src)
288− Can.IncomingPort name tipe ->
289− Opt.IncomingPort name <$> Port.toDecoder tipe
291− Can.Program main expr ->
292− Opt.Program <$> optimizeMain main <*> justConvert expr
294− Can.SaveEnv _ _ ->
155+-- DEFINITION
295− error "save_the_environment should never make it to optimization phase"
297− Can.GLShader _ src _ ->
298− pure (Opt.GLShader src)
158+optimizeDef :: Can.Def -> Opt.Expr -> Names.Tracker Opt.Expr
159+optimizeDef 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
304−
168+optimizeDefHelp :: N.Name -> [Can.Pattern] -> Can.Expr -> Opt.Expr -> Names.Tracker Opt.Expr
305−optimizeVariable :: R.Region -> Var.Canonical -> Env.Optimizer Opt.Expr
169+optimizeDefHelp name args expr body =
306−optimizeVariable region (Var.Canonical home name) =
309− pure (Opt.VarLocal name)
312− pure (Opt.VarLocal name)
314− Var.TopLevel modul ->
315− do let var = Var.Global modul name
317− pure (Opt.VarGlobal var)
320− do let var = Var.Global modul name
322− if name == "crash" && modul == ModuleName.inCore "Debug"
324− do here <- Env.getHome
325− pure (Opt.Crash here region Nothing)
327− pure (Opt.VarGlobal var)
334−optimizeMain :: Can.Main -> Env.Optimizer Opt.Main
336− case main of
170+ case args of
337− Can.Static ->
171+ [] ->
341− Opt.Dynamic <$> Port.toFlagsDecoder tipe
345−-- OPTIMIZE CASE BRANCHES
352− -> (P.Canonical, Can.Expr)
353− -> Env.Optimizer (P.Canonical, Opt.Expr)
354−optimizeBranch context region exprName (rawPattern, canBranch) =
355− do optBranch <- optimizeExpr context canBranch
172+ do oexpr <- optimizeExpr expr
356− (pattern, branch) <- tagCrashBranch region rawPattern optBranch
173+ pure $ Opt.Let (Opt.Def name oexpr) body
358− let substitutions = Map.fromList $
359− patternToSubstitutions (Opt.VarLocal exprName) pattern
361− (,) pattern <$> Inline.inline substitutions branch
368− -> Env.Optimizer (P.Canonical, Opt.Expr)
369−tagCrashBranch region pattern@(A.A pr _) expr =
371− Opt.Call (Opt.Crash home _ _) [arg] ->
372− do name <- Env.freshName
374− ( A.A pr (P.Alias name pattern)
375− , Opt.Call (Opt.Crash home region (Just (Opt.VarLocal name))) [arg]
379− return (pattern, expr)
176+ do (argNames, defss) <- destructArgs args
380−
177+ let func = Opt.Function argNames (foldr Opt.Let body (concat defss))
382−
179+ Opt.Let (Opt.Def name func) body
386−getTailCallInfo :: Context -> Can.Expr -> Int -> Maybe (Text, [Text])
387−getTailCallInfo context (A.A _ function) arity =
388− case (context, function) of
389− ( Just (ctxName, ctxArity, argNames), Can.Var (Var.Canonical home name) ) ->
391− if name == ctxName && arity == ctxArity && Var.isLocalHome home then
183+-- DESTRUCTURING
392− Just (name, argNames)
397− _ ->
186+destructArgs :: [Can.Pattern] -> Names.Tracker ([N.Name], [[Opt.Def]])
398− Nothing
187+destructArgs args =
188+ unzip <$> traverse destruct args
191+destruct :: Can.Pattern -> Names.Tracker (N.Name, [Opt.Def])
192+destruct pattern@(A.At _ ptrn) =
402−-- DEPATTERN
197+ Can.PAlias subPattern name ->
403−-- given a pattern and an expression, push the actual pattern matching into the
198+ do revDefs <- destructHelp (Opt.VarLocal name) subPattern []
404−-- expression as a case-expression if necessary. The pattern compiler will work
199+ pure (name, reverse revDefs)
202+ do name <- Names.generate
203+ revDefs <- destructHelp (Opt.VarLocal name) pattern []
204+ pure (name, reverse revDefs)
408−depattern :: P.Canonical -> Can.Expr -> Env.Optimizer (Text, Can.Expr)
409−depattern canPattern@(A.A _ pattern) expr =
412− A.A (error "the annotation added in 'depattern' should not be observed!")
414− caseExpr e branches =
415− ann (Can.Case e branches)
418− ann (Can.Var (Var.local name))
420− caseify =
207+destructHelp :: Opt.Expr -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
421− do name <- Env.freshName
208+destructHelp root (A.At region pattern) revDefs =
424− , caseExpr (var name) [ (canPattern, expr) ]
427 case pattern of
209 case pattern of
428− P.Var name ->
210+ Can.PAnything ->
429− return (name, expr)
211+ pure revDefs
431− P.Literal _ ->
213+ Can.PVar name ->
432− caseify
214+ pure (Opt.Def name root : revDefs)
434− P.Record _ ->
216+ Can.PRecord fields ->
219+ Opt.Def field (Opt.Access root field)
221+ pure (map toDef fields ++ revDefs)
437− P.Anything ->
223+ Can.PAlias subPattern name ->
438− do name <- Env.freshName
224+ destructHelp (Opt.VarLocal name) subPattern $
439− return (name, expr)
225+ Opt.Def name root : revDefs
441− P.Alias _ _ ->
227+ Can.PUnit ->
442− caseify
228+ pure revDefs
444− P.Ctor _ _ ->
230+ Can.PTuple a b maybeC ->
445− caseify
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
449−-- OPTIMIZE BINOPS
247+ Can.PList (hd:tl) ->
248+ destructCons root hd (A.At region (Can.PList tl)) revDefs
251+ destructCons root hd tl revDefs
456− -> Can.Expr
253+ Can.PChr _ ->
457− -> Can.Expr
254+ pure revDefs
458− -> Env.Optimizer Opt.Expr
459−optimizeBinop context region op leftExpr rightExpr =
462− binop = ann (Can.Binop op leftExpr rightExpr)
464− if op == forwardApply then
466− optimizeExpr context (collect id left forwardApply binop)
256+ Can.PStr _ ->
468− else if op == backwardApply then
259+ Can.PInt _ ->
470− optimizeExpr context (collect id right backwardApply binop)
262+ Can.PCtor _ _ _ _ _ args ->
263+ do name <- Names.generate
265+ (destructCtorArg (Opt.VarLocal name))
266+ (Opt.Def name root : revDefs)
472− else if op == forwardCompose then
474− do var <- Env.freshName
270+destructCons :: Opt.Expr -> Can.Pattern -> Can.Pattern -> [Opt.Def] -> Names.Tracker [Opt.Def]
475− let makeRoot func = ann (Can.App func (ann (Can.Var (Var.local var))))
271+destructCons root hd tl revDefs =
476− let body = collect makeRoot left forwardCompose binop
272+ do name <- Names.generate
477− optimizeExpr context (ann (Can.Lambda (ann (P.Var var)) body))
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)
479− else if op == backwardCompose then
481− do var <- Env.freshName
278+destructCtorArg :: Opt.Expr -> [Opt.Def] -> Can.PatternCtorArg -> Names.Tracker [Opt.Def]
482− let makeRoot func = ann (Can.App func (ann (Can.Var (Var.local var))))
279+destructCtorArg root revDefs (Can.PatternCtorArg index _ arg) =
483− let body = collect makeRoot right backwardCompose binop
280+ destructHelp (Opt.CtorAccess root index) arg revDefs
484− optimizeExpr context (ann (Can.Lambda (ann (P.Var var)) body))
486− else if op == cons then
488− optimizeExpr context (ann (Can.Ctor cons [ leftExpr, rightExpr ]))
492− do optLeft <- optimizeExpr Nothing leftExpr
284+-- TAIL CALL
493− optRight <- optimizeExpr Nothing rightExpr
494− makeOptBinop op optLeft optRight
497−-- left-associative ((x |> f) |> g)
287+optimizePotentialTailCall :: Can.Def -> Names.Tracker Opt.Def
498−forwardApply :: Var.Canonical
288+optimizePotentialTailCall def =
499−forwardApply =
289+ case def of
500− Var.inCore "Basics" "|>"
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
503−-- right-associative (g <| (f <| x))
504−backwardApply :: Var.Canonical
506− Var.inCore "Basics" "<|"
301+optimizeTailExpr :: N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
302+optimizeTailExpr 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
308+ optimizeExpr locExpr
509−-- left-associative ((f >> g) >> h)
310+ Can.If branches finally ->
510−forwardCompose :: Var.Canonical
311+ let
511−forwardCompose =
312+ optimizeBranch (condition, branch) =
512− Var.inCore "Basics" ">>"
313+ (,)
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 ->
515−-- right-associative (h << (g << f))
345+ _ ->
516−backwardCompose :: Var.Canonical
346+ optimizeExpr locExpr
518− Var.inCore "Basics" "<<"
521−cons :: Var.Canonical
523− Var.Canonical Var.BuiltIn "::"
527− Can.Expr -> Can.Expr -> (Can.Expr, Can.Expr)
353+toTailDef :: N.Name -> [N.Name] -> [[Opt.Def]] -> Opt.Expr -> Opt.Def
354+toTailDef 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)))
361+hasTailCall :: Opt.Expr -> Bool
362+hasTailCall expression =
364+ Opt.TailCall _ _ _ ->
535−right :: Assoc
367+ Opt.If branches finally ->
536−right =
368+ hasTailCall finally || any (hasTailCall . snd) branches
540−collect :: (Can.Expr -> Can.Expr) -> Assoc -> Var.Canonical -> Can.Expr -> Can.Expr
373+ Opt.Case _ _ branches ->
541−collect makeRoot assoc desiredOp annExpr@(A.A ann expr) =
374+ any (hasTailCall . snd) branches
543− Can.Binop op leftExpr rightExpr | op == desiredOp ->
545− (func, arg) = assoc leftExpr rightExpr
547− A.A ann (Can.App func (collect makeRoot assoc desiredOp arg))
550− makeRoot annExpr
377+ False
553−makeOptBinop :: Var.Canonical -> Opt.Expr -> Opt.Expr -> Env.Optimizer Opt.Expr
554−makeOptBinop (Var.Canonical home op) leftExpr rightExpr =
557− error "bug manifesting in Optimize.makeOptBinop"
560− error "bug manifesting in Optimize.makeOptBinop"
563− do let var = Var.Global name op
565− return $ Opt.Binop var leftExpr rightExpr
567− Var.TopLevel name ->
568− do let var = Var.Global name op
570− return $ Opt.Binop var leftExpr rightExpr