@@ -2,9 +2,12 @@
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Optimize (optimize) where
3module Optimize (optimize) where
5+import Control.Arrow (second)
5import qualified Control.Monad as M
6import qualified Control.Monad as M
7+import Data.Monoid ((<>))
6import qualified Data.Map as Map
8import qualified Data.Map as Map
7−import qualified Data.Traversable as T
9+import qualified Data.Set as Set
10+import qualified Data.Text as Text
8import Data.Text (Text)
11import Data.Text (Text)
10import qualified AST.Expression.Canonical as Can
13import qualified AST.Expression.Canonical as Can
@@ -24,77 +27,95 @@ import qualified Reporting.Region as R
24-- OPTIMIZE
27-- OPTIMIZE
27−optimize :: DT.VariantDict -> ModuleName.Canonical -> [Can.Def] -> [Opt.Def]
30+optimize :: DT.VariantDict -> ModuleName.Canonical -> [Can.Def] -> [(Text, Opt.Decl)]
28optimize variantDict home defs =
31optimize variantDict home defs =
29− Env.run variantDict home (concat <$> mapM (optimizeDef True) defs)
32+ concat $ zipWith (optimizeDecl variantDict home) [1 .. length defs] defs
33−-- CONVERT DEFINITIONS
36+-- OPTIMIZE DECLS
36−optimizeDef :: Bool -> Can.Def -> Env.Optimizer [Opt.Def]
39+optimizeDecl :: DT.VariantDict -> ModuleName.Canonical -> Int -> Can.Def -> [(Text, Opt.Decl)]
37−optimizeDef isRoot (Can.Def _ pattern expression _) =
40+optimizeDecl variantDict home index (Can.Def _ pattern@(A.A _ ptrn) expression _) =
39− (args, canBody) =
42+ (rawArgs, rawBody) =
40 Can.collectLambdas expression
43 Can.collectLambdas expression
45+ case (ptrn, rawArgs) of
47+ (:[]) $ Env.run variantDict home $
48+ optimizeNamedDef name rawArgs rawBody
42− maybeGetHome =
50+ (_, []) ->
43− if isRoot then
51+ let
44− Just <$> Env.getHome
52+ name = "_" <> Text.pack (show index)
53+ deps = Set.singleton (Var.Global home name)
55+ Env.run variantDict home $
56+ ((,) name . Opt.Def) <$> optimizeExpr Nothing rawBody
58+ destruct (Var.topLevel home name) pattern
60+ decl : map (second (Opt.Decl deps Nothing)) destructors
47− return Nothing
63+ error "bug manifesting in Optimize.optimizeDecl, please report"
49− do home <- maybeGetHome
50− optimizeDefHelp home pattern args canBody
54− :: Maybe ModuleName.Canonical
67+-- OPTIMIZE DEFS
58− -> Env.Optimizer [Opt.Def]
70+optimizeLetDef :: Can.Def -> Env.Optimizer [(Text, Opt.Def)]
59−optimizeDefHelp home pattern@(A.A _ ptrn) rawArgs rawBody =
71+optimizeLetDef (Can.Def _ pattern@(A.A _ ptrn) expression _) =
61− facts =
73+ (rawArgs, rawBody) =
62− Opt.Facts home
74+ Can.collectLambdas expression
64− case (ptrn, rawArgs) of
76+ case (ptrn, rawArgs) of
65− (P.Var name, _ : _) ->
77+ (P.Var name, _) ->
78+ do def <- optimizeNamedDef name rawArgs rawBody
67− do htc <- Env.getTailCall
81+ (_, []) ->
68− Env.setTailCall False
82+ do name <- Env.freshName
83+ body <- optimizeExpr Nothing rawBody
84+ return $ (name, Opt.Def body) : destruct (Var.local name) pattern
70− (args, body) <- optimizeFunction (Just name) rawArgs rawBody
86+ _ ->
87+ error "bug manifesting in Optimize.optimizeLetDef, please report"
72− isTailCall <- Env.getTailCall
90+optimizeNamedDef :: Text -> [P.Canonical] -> Can.Expr -> Env.Optimizer (Text, Opt.Def)
91+optimizeNamedDef name rawArgs rawBody =
94+ do hasTailCall <- Env.getTailCall
95+ body <- optimizeExpr Nothing rawBody
96+ Env.setTailCall hasTailCall
75− return $
97+ return (name, Opt.Def body)
77− [ Opt.TailDef facts name args body ]
80− [ Opt.Def facts name (Opt.Function args body) ]
100+ do htc <- Env.getTailCall
101+ Env.setTailCall False
82− (P.Var name, []) ->
103+ (args, body) <- optimizeFunction (Just name) rawArgs rawBody
84− do hasTailCall <- Env.getTailCall
105+ isTailCall <- Env.getTailCall
85− body <- optimizeExpr Nothing rawBody
86− Env.setTailCall hasTailCall
106+ Env.setTailCall htc
87− return [ Opt.Def facts name body ]
89− (_, []) ->
108+ return $ (,) name $
110+ Opt.TailDef args body
112+ Opt.Def (Opt.Function args body)
91− do name <- Env.freshName
92− optBody <- optimizeExpr Nothing rawBody
93− let optDef = Opt.Def facts name optBody
94− return (optDef : patternToDefs home name pattern)
96− _ ->
115+destruct :: Var.Canonical -> P.Canonical -> [(Text, Opt.Def)]
97− error "there should never be a function where the name is not a P.Var"
116+destruct var pattern =
117+ map (second Opt.Def) $
118+ patternToSubstitutions (Opt.Var var) pattern
@@ -114,30 +135,13 @@ optimizeFunction maybeName patterns givenBody =
115makeContext :: [Text] -> Text -> Context
136makeContext :: [Text] -> Text -> Context
116makeContext argNames name =
137makeContext argNames name =
117− Just (name, length argNames, argNames)
138+ Just (name, length argNames, argNames)
120depatternArgs :: ([Text], Can.Expr) -> P.Canonical -> Env.Optimizer ([Text], Can.Expr)
141depatternArgs :: ([Text], Can.Expr) -> P.Canonical -> Env.Optimizer ([Text], Can.Expr)
121depatternArgs (names, rawExpr) ptrn =
142depatternArgs (names, rawExpr) ptrn =
122− do (name, expr) <- depattern ptrn rawExpr
143+ do (name, expr) <- depattern ptrn rawExpr
123− return (name : names, expr)
144+ return (name : names, expr)
126−patternToDefs :: Maybe ModuleName.Canonical -> Text -> P.Canonical -> [Opt.Def]
127−patternToDefs home rootName pattern =
132− Opt.Var (Var.local rootName)
135− Opt.Var (Var.topLevel moduleName rootName)
137− toDef (name, accessExpr) =
138− Opt.Def (Opt.Facts home) name accessExpr
140− map toDef (patternToSubstitutions rootExpr pattern)
@@ -196,16 +200,17 @@ optimizeExpr context annExpr@(A.A region expression) =
196 pure (Opt.Literal lit)
200 pure (Opt.Literal lit)
198 Can.Var name ->
202 Can.Var name ->
199− if name == Var.inCore "Debug" "crash" then
203+ do Env.register name
204+ if name == debugCrash
200− do home <- Env.getHome
206+ do home <- Env.getHome
201− pure (Opt.Crash home region Nothing)
207+ pure (Opt.Crash home region Nothing)
204− pure (Opt.Var name)
209+ pure (Opt.Var name)
206 Can.List elements ->
211 Can.List elements ->
208− <$> T.traverse justConvert elements
213+ <$> traverse justConvert elements
210 Can.Binop op leftExpr rightExpr ->
215 Can.Binop op leftExpr rightExpr ->
211 optimizeBinop context region op leftExpr rightExpr
216 optimizeBinop context region op leftExpr rightExpr
@@ -224,14 +229,14 @@ optimizeExpr context annExpr@(A.A region expression) =
225 case getTailCallInfo context func (length args) of
230 case getTailCallInfo context func (length args) of
226 Just (name, argNames) ->
231 Just (name, argNames) ->
227− do optArgs <- T.traverse justConvert args
232+ do optArgs <- traverse justConvert args
228 Env.setTailCall True
233 Env.setTailCall True
229 return (Opt.TailCall name argNames optArgs)
234 return (Opt.TailCall name argNames optArgs)
231 Nothing ->
236 Nothing ->
232 do hasTailCall <- Env.getTailCall
237 do hasTailCall <- Env.getTailCall
233 optFunc <- justConvert func
238 optFunc <- justConvert func
234− optArgs <- T.traverse justConvert args
239+ optArgs <- traverse justConvert args
235 Env.setTailCall hasTailCall
240 Env.setTailCall hasTailCall
236 return (Opt.Call optFunc optArgs)
241 return (Opt.Call optFunc optArgs)
@@ -241,11 +246,11 @@ optimizeExpr context annExpr@(A.A region expression) =
241 (,) <$> justConvert cond <*> keepLooking branch
246 (,) <$> justConvert cond <*> keepLooking branch
244− <$> T.traverse crawlBranch branches
249+ <$> traverse crawlBranch branches
245 <*> keepLooking finally
250 <*> keepLooking finally
247 Can.Let defs body ->
252 Can.Let defs body ->
248− do optDefs <- concat <$> T.traverse (optimizeDef False) defs
253+ do optDefs <- concat <$> traverse optimizeLetDef defs
249 Opt.Let optDefs <$> keepLooking body
254 Opt.Let optDefs <$> keepLooking body
251 Can.Case expr branches ->
256 Can.Case expr branches ->
@@ -253,12 +258,12 @@ optimizeExpr context annExpr@(A.A region expression) =
253 variantDict <- Env.getVariantDict
258 variantDict <- Env.getVariantDict
255 name <- Env.freshName
260 name <- Env.freshName
256− optBranches <- T.traverse (optimizeBranch context region name) branches
261+ optBranches <- traverse (optimizeBranch context region name) branches
257 let optCase = Case.optimize variantDict name optBranches
262 let optCase = Case.optimize variantDict name optBranches
258− return $ Opt.Let [ Opt.Def Opt.dummyFacts name optExpr ] optCase
263+ return $ Opt.Let [ (name, Opt.Def optExpr) ] optCase
260 Can.Ctor (Var.Canonical _ name) exprs ->
265 Can.Ctor (Var.Canonical _ name) exprs ->
261− Opt.Ctor name <$> T.traverse justConvert exprs
266+ Opt.Ctor name <$> traverse justConvert exprs
263 Can.Access record field ->
268 Can.Access record field ->
264 Opt.Access
269 Opt.Access
@@ -268,17 +273,17 @@ optimizeExpr context annExpr@(A.A region expression) =
268 Can.Update record fields ->
273 Can.Update record fields ->
269 Opt.Update
274 Opt.Update
270 <$> justConvert record
275 <$> justConvert record
271− <*> T.traverse (mapSnd justConvert) fields
276+ <*> traverse (traverse justConvert) fields
273 Can.Record fields ->
278 Can.Record fields ->
274 Opt.Record
279 Opt.Record
275− <$> T.traverse (mapSnd justConvert) fields
280+ <$> traverse (traverse justConvert) fields
277− Can.Cmd moduleName ->
282+ Can.Cmd moduleName manager ->
278− pure (Opt.Cmd moduleName)
283+ Opt.Cmd moduleName <$> Env.registerEffects manager
280− Can.Sub moduleName ->
285+ Can.Sub moduleName manager ->
281− pure (Opt.Sub moduleName)
286+ Opt.Sub moduleName <$> Env.registerEffects manager
283 Can.OutgoingPort name tipe ->
288 Can.OutgoingPort name tipe ->
284 pure (Opt.OutgoingPort name tipe)
289 pure (Opt.OutgoingPort name tipe)
@@ -296,11 +301,6 @@ optimizeExpr context annExpr@(A.A region expression) =
296 pure (Opt.GLShader uid src gltipe)
301 pure (Opt.GLShader uid src gltipe)
299−mapSnd :: M.Functor box => (a -> box b) -> (x, a) -> box (x, b)
305-- OPTIMIZE CASE BRANCHES
305-- OPTIMIZE CASE BRANCHES
@@ -487,6 +487,11 @@ cons =
487 Var.Canonical Var.BuiltIn "::"
487 Var.Canonical Var.BuiltIn "::"
490+debugCrash :: Var.Canonical
492+ Var.inCore "Debug" "crash"
490type Assoc =
495type Assoc =
491 Can.Expr -> Can.Expr -> (Can.Expr, Can.Expr)
496 Can.Expr -> Can.Expr -> (Can.Expr, Can.Expr)