@@ -2,9 +2,12 @@
22{-# LANGUAGE OverloadedStrings #-}
33module Optimize (optimize) where
44
5+import Control.Arrow (second)
56import qualified Control.Monad as M
7+import Data.Monoid ((<>))
68import 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
811import Data.Text (Text)
912
1013import qualified AST.Expression.Canonical as Can
@@ -24,77 +27,95 @@ import qualified Reporting.Region as R
2427-- OPTIMIZE
2528
2629
27−optimize :: DT.VariantDict -> ModuleName.Canonical -> [Can.Def] -> [Opt.Def]
30+optimize :: DT.VariantDict -> ModuleName.Canonical -> [Can.Def] -> [(Text, Opt.Decl)]
2831optimize variantDict home defs =
29− Env.run variantDict home (concat <$> mapM (optimizeDef True) defs)
32+ concat $ zipWith (optimizeDecl variantDict home) [1 .. length defs] defs
3033
3134
3235
33−-- CONVERT DEFINITIONS
36+-- OPTIMIZE DECLS
3437
3538
36−optimizeDef :: Bool -> Can.Def -> Env.Optimizer [Opt.Def]
37−optimizeDef isRoot (Can.Def _ pattern expression _) =
39+optimizeDecl :: DT.VariantDict -> ModuleName.Canonical -> Int -> Can.Def -> [(Text, Opt.Decl)]
40+optimizeDecl variantDict home index (Can.Def _ pattern@(A.A _ ptrn) expression _) =
3841 let
39− (args, canBody) =
42+ (rawArgs, rawBody) =
4043 Can.collectLambdas expression
44+ in
45+ case (ptrn, rawArgs) of
46+ (P.Var name, _) ->
47+ (:[]) $ Env.run variantDict home $
48+ optimizeNamedDef name rawArgs rawBody
4149
42− maybeGetHome =
43− if isRoot then
44− Just <$> Env.getHome
50+ (_, []) ->
51+ let
52+ name = "_" <> Text.pack (show index)
53+ deps = Set.singleton (Var.Global home name)
54+ decl =
55+ Env.run variantDict home $
56+ ((,) name . Opt.Def) <$> optimizeExpr Nothing rawBody
57+ destructors =
58+ destruct (Var.topLevel home name) pattern
59+ in
60+ decl : map (second (Opt.Decl deps Nothing)) destructors
4561
46− else
47− return Nothing
48− in
49− do home <- maybeGetHome
50− optimizeDefHelp home pattern args canBody
62+ _ ->
63+ error "bug manifesting in Optimize.optimizeDecl, please report"
5164
5265
53−optimizeDefHelp
54− :: Maybe ModuleName.Canonical
55− -> P.Canonical
56− -> [P.Canonical]
57− -> Can.Expr
58− -> Env.Optimizer [Opt.Def]
59−optimizeDefHelp home pattern@(A.A _ ptrn) rawArgs rawBody =
66+
67+-- OPTIMIZE DEFS
68+
69+
70+optimizeLetDef :: Can.Def -> Env.Optimizer [(Text, Opt.Def)]
71+optimizeLetDef (Can.Def _ pattern@(A.A _ ptrn) expression _) =
6072 let
61− facts =
62− Opt.Facts home
73+ (rawArgs, rawBody) =
74+ Can.collectLambdas expression
6375 in
64− case (ptrn, rawArgs) of
65− (P.Var name, _ : _) ->
76+ case (ptrn, rawArgs) of
77+ (P.Var name, _) ->
78+ do def <- optimizeNamedDef name rawArgs rawBody
79+ return [def]
6680
67− do htc <- Env.getTailCall
68− Env.setTailCall False
81+ (_, []) ->
82+ do name <- Env.freshName
83+ body <- optimizeExpr Nothing rawBody
84+ return $ (name, Opt.Def body) : destruct (Var.local name) pattern
6985
70− (args, body) <- optimizeFunction (Just name) rawArgs rawBody
86+ _ ->
87+ error "bug manifesting in Optimize.optimizeLetDef, please report"
7188
72− isTailCall <- Env.getTailCall
73− Env.setTailCall htc
7489
75− return $
76− if isTailCall then
77− [ Opt.TailDef facts name args body ]
90+optimizeNamedDef :: Text -> [P.Canonical] -> Can.Expr -> Env.Optimizer (Text, Opt.Def)
91+optimizeNamedDef name rawArgs rawBody =
92+ case rawArgs of
93+ [] ->
94+ do hasTailCall <- Env.getTailCall
95+ body <- optimizeExpr Nothing rawBody
96+ Env.setTailCall hasTailCall
97+ return (name, Opt.Def body)
7898
79− else
80− [ Opt.Def facts name (Opt.Function args body) ]
99+ _ : _ ->
100+ do htc <- Env.getTailCall
101+ Env.setTailCall False
81102
82− (P.Var name, []) ->
103+ (args, body) <- optimizeFunction (Just name) rawArgs rawBody
83104
84− do hasTailCall <- Env.getTailCall
85− body <- optimizeExpr Nothing rawBody
86− Env.setTailCall hasTailCall
87− return [ Opt.Def facts name body ]
105+ isTailCall <- Env.getTailCall
106+ Env.setTailCall htc
88107
89− (_, []) ->
108+ return $ (,) name $
109+ if isTailCall then
110+ Opt.TailDef args body
111+ else
112+ Opt.Def (Opt.Function args body)
90113
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)
95114
96− _ ->
97− error "there should never be a function where the name is not a P.Var"
115+destruct :: Var.Canonical -> P.Canonical -> [(Text, Opt.Def)]
116+destruct var pattern =
117+ map (second Opt.Def) $
118+ patternToSubstitutions (Opt.Var var) pattern
98119
99120
100121
@@ -114,30 +135,13 @@ optimizeFunction maybeName patterns givenBody =
114135
115136makeContext :: [Text] -> Text -> Context
116137makeContext argNames name =
117− Just (name, length argNames, argNames)
138+ Just (name, length argNames, argNames)
118139
119140
120141depatternArgs :: ([Text], Can.Expr) -> P.Canonical -> Env.Optimizer ([Text], Can.Expr)
121142depatternArgs (names, rawExpr) ptrn =
122− do (name, expr) <- depattern ptrn rawExpr
123− return (name : names, expr)
124−
125−
126−patternToDefs :: Maybe ModuleName.Canonical -> Text -> P.Canonical -> [Opt.Def]
127−patternToDefs home rootName pattern =
128− let
129− rootExpr =
130− case home of
131− Nothing ->
132− Opt.Var (Var.local rootName)
133−
134− Just moduleName ->
135− Opt.Var (Var.topLevel moduleName rootName)
136−
137− toDef (name, accessExpr) =
138− Opt.Def (Opt.Facts home) name accessExpr
139− in
140− map toDef (patternToSubstitutions rootExpr pattern)
143+ do (name, expr) <- depattern ptrn rawExpr
144+ return (name : names, expr)
141145
142146
143147
@@ -196,16 +200,17 @@ optimizeExpr context annExpr@(A.A region expression) =
196200 pure (Opt.Literal lit)
197201
198202 Can.Var name ->
199− if name == Var.inCore "Debug" "crash" then
200− do home <- Env.getHome
201− pure (Opt.Crash home region Nothing)
202−
203− else
204− pure (Opt.Var name)
203+ do Env.register name
204+ if name == debugCrash
205+ then
206+ do home <- Env.getHome
207+ pure (Opt.Crash home region Nothing)
208+ else
209+ pure (Opt.Var name)
205210
206211 Can.List elements ->
207212 Opt.List
208− <$> T.traverse justConvert elements
213+ <$> traverse justConvert elements
209214
210215 Can.Binop op leftExpr rightExpr ->
211216 optimizeBinop context region op leftExpr rightExpr
@@ -224,14 +229,14 @@ optimizeExpr context annExpr@(A.A region expression) =
224229 in
225230 case getTailCallInfo context func (length args) of
226231 Just (name, argNames) ->
227− do optArgs <- T.traverse justConvert args
232+ do optArgs <- traverse justConvert args
228233 Env.setTailCall True
229234 return (Opt.TailCall name argNames optArgs)
230235
231236 Nothing ->
232237 do hasTailCall <- Env.getTailCall
233238 optFunc <- justConvert func
234− optArgs <- T.traverse justConvert args
239+ optArgs <- traverse justConvert args
235240 Env.setTailCall hasTailCall
236241 return (Opt.Call optFunc optArgs)
237242
@@ -241,11 +246,11 @@ optimizeExpr context annExpr@(A.A region expression) =
241246 (,) <$> justConvert cond <*> keepLooking branch
242247 in
243248 Opt.If
244− <$> T.traverse crawlBranch branches
249+ <$> traverse crawlBranch branches
245250 <*> keepLooking finally
246251
247252 Can.Let defs body ->
248− do optDefs <- concat <$> T.traverse (optimizeDef False) defs
253+ do optDefs <- concat <$> traverse optimizeLetDef defs
249254 Opt.Let optDefs <$> keepLooking body
250255
251256 Can.Case expr branches ->
@@ -253,12 +258,12 @@ optimizeExpr context annExpr@(A.A region expression) =
253258 variantDict <- Env.getVariantDict
254259
255260 name <- Env.freshName
256− optBranches <- T.traverse (optimizeBranch context region name) branches
261+ optBranches <- traverse (optimizeBranch context region name) branches
257262 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
259264
260265 Can.Ctor (Var.Canonical _ name) exprs ->
261− Opt.Ctor name <$> T.traverse justConvert exprs
266+ Opt.Ctor name <$> traverse justConvert exprs
262267
263268 Can.Access record field ->
264269 Opt.Access
@@ -268,17 +273,17 @@ optimizeExpr context annExpr@(A.A region expression) =
268273 Can.Update record fields ->
269274 Opt.Update
270275 <$> justConvert record
271− <*> T.traverse (mapSnd justConvert) fields
276+ <*> traverse (traverse justConvert) fields
272277
273278 Can.Record fields ->
274279 Opt.Record
275− <$> T.traverse (mapSnd justConvert) fields
280+ <$> traverse (traverse justConvert) fields
276281
277− Can.Cmd moduleName ->
278− pure (Opt.Cmd moduleName)
282+ Can.Cmd moduleName manager ->
283+ Opt.Cmd moduleName <$> Env.registerEffects manager
279284
280− Can.Sub moduleName ->
281− pure (Opt.Sub moduleName)
285+ Can.Sub moduleName manager ->
286+ Opt.Sub moduleName <$> Env.registerEffects manager
282287
283288 Can.OutgoingPort name tipe ->
284289 pure (Opt.OutgoingPort name tipe)
@@ -296,11 +301,6 @@ optimizeExpr context annExpr@(A.A region expression) =
296301 pure (Opt.GLShader uid src gltipe)
297302
298303
299−mapSnd :: M.Functor box => (a -> box b) -> (x, a) -> box (x, b)
300−mapSnd func (x, a) =
301− (,) x <$> func a
302−
303−
304304
305305-- OPTIMIZE CASE BRANCHES
306306
@@ -487,6 +487,11 @@ cons =
487487 Var.Canonical Var.BuiltIn "::"
488488
489489
490+debugCrash :: Var.Canonical
491+debugCrash =
492+ Var.inCore "Debug" "crash"
493+
494+
490495type Assoc =
491496 Can.Expr -> Can.Expr -> (Can.Expr, Can.Expr)
492497