on master help sign in
Fix bug in code gen for cyclic definitions

The old version made it possible to skip functions in the cycle if they were not used directly outside the cycle. New version ensures that the whole cycle is generated together.

commit402b21a86897bac93f7d8c18de09421128731f52 authorEvan Czaplicki <evancz@users.noreply.github.com> dateTue 22 May 2018, 20:12 (8 years ago) parent3521750
5 files changed+75−70
builder/src/Generate/Nitpick.hs+1−1 compiler/src/AST/Optimized.hs+3−3 compiler/src/Generate/JavaScript.hs+18−7 compiler/src/Optimize/Expression.hs+14−12 compiler/src/Optimize/Module.hs+39−47
builder/src/Generate/Nitpick.hs+1−1
@@ -39,7 +39,7 @@ nodeHasDebug node =
3939 Opt.Enum _ -> False
4040 Opt.Box -> False
4141 Opt.Link _ -> False
42− Opt.Cycle defs _ -> any (hasDebug . snd) defs
42+ Opt.Cycle vs fs _ -> any (hasDebug . snd) vs || any defHasDebug fs
4343 Opt.Manager _ -> False
4444 Opt.Kernel _ _ -> False
4545 Opt.PortIncoming expr _ -> hasDebug expr
compiler/src/AST/Optimized.hs+3−3
@@ -150,7 +150,7 @@ data Node
150150 | Enum Index.ZeroBased
151151 | Box
152152 | Link Global
153− | Cycle [(N.Name, Expr)] (Set.Set Global)
153+ | Cycle [(N.Name, Expr)] [Def] (Set.Set Global)
154154 | Manager EffectsType
155155 | Kernel KContent (Maybe KContent)
156156 | PortIncoming Expr (Set.Set Global)
@@ -344,7 +344,7 @@ instance Binary Node where
344344 Enum a -> putWord8 3 >> put a
345345 Box -> putWord8 4
346346 Link a -> putWord8 5 >> put a
347− Cycle a b -> putWord8 6 >> put a >> put b
347+ Cycle a b c -> putWord8 6 >> put a >> put b >> put c
348348 Manager a -> putWord8 7 >> put a
349349 Kernel a b -> putWord8 8 >> put a >> put b
350350 PortIncoming a b -> putWord8 9 >> put a >> put b
@@ -359,7 +359,7 @@ instance Binary Node where
359359 3 -> liftM Enum get
360360 4 -> return Box
361361 5 -> liftM Link get
362− 6 -> liftM2 Cycle get get
362+ 6 -> liftM3 Cycle get get get
363363 7 -> liftM Manager get
364364 8 -> liftM2 Kernel get get
365365 9 -> liftM2 PortIncoming get get
compiler/src/Generate/JavaScript.hs+18−7
@@ -180,9 +180,9 @@ addGlobalHelp mode graph global state =
180180 Opt.Link linkedGlobal ->
181181 addGlobal mode graph state linkedGlobal
182182
183− Opt.Cycle cycle deps ->
183+ Opt.Cycle values functions deps ->
184184 addStmt (addDeps deps state) (
185− generateCycle mode global cycle
185+ generateCycle mode global values functions
186186 )
187187
188188 Opt.Manager effectsType ->
@@ -249,13 +249,24 @@ isDebugger (Opt.Global (ModuleName.Canonical _ home) _) =
249249-- GENERATE CYCLES
250250
251251
252−generateCycle :: Mode.Mode -> Opt.Global -> [(N.Name, Opt.Expr)] -> JS.Stmt
253−generateCycle mode (Opt.Global home _) cycle =
252+generateCycle :: Mode.Mode -> Opt.Global -> [(N.Name, Opt.Expr)] -> [Opt.Def] -> JS.Stmt
253+generateCycle mode (Opt.Global home _) values functions =
254254 let
255− safeDefs = map (generateSafeCycle mode home) cycle
256− realDefs = map (generateRealCycle home) cycle
255+ funcDefs = map (generateCycleFunc mode home) functions
256+ safeDefs = map (generateSafeCycle mode home) values
257+ realDefs = map (generateRealCycle home) values
257258 in
258− JS.Block (safeDefs ++ realDefs)
259+ JS.Block (funcDefs ++ safeDefs ++ realDefs)
260+
261+
262+generateCycleFunc :: Mode.Mode -> ModuleName.Canonical -> Opt.Def -> JS.Stmt
263+generateCycleFunc mode home def =
264+ case def of
265+ Opt.Def name expr ->
266+ JS.Var [ (Name.fromGlobal home name, Just (Expr.codeToExpr (Expr.generate mode expr))) ]
267+
268+ Opt.TailDef name args expr ->
269+ JS.Var [ (Name.fromGlobal home name, Just (Expr.codeToExpr (Expr.generateTailDef mode name args expr))) ]
259270
260271
261272generateSafeCycle :: Mode.Mode -> ModuleName.Canonical -> (N.Name, Opt.Expr) -> JS.Stmt
compiler/src/Optimize/Expression.hs+14−12
@@ -1,8 +1,7 @@
11{-# OPTIONS_GHC -Wall #-}
22{-# LANGUAGE OverloadedStrings #-}
33module Optimize.Expression
4− ( Cycle
5− , optimize
4+ ( optimize
65 , destructArgs
76 , optimizePotentialTailCall
87 )
@@ -113,7 +112,7 @@ optimize cycle (A.At region expression) =
113112 case defs of
114113 [def] ->
115114 Opt.Let
116− <$> optimizePotentialTailCall cycle def
115+ <$> optimizePotentialTailCallDef cycle def
117116 <*> optimize cycle body
118117
119118 _ ->
@@ -342,18 +341,21 @@ destructCtorArg path revDs (Can.PatternCtorArg index _ arg) =
342341-- TAIL CALL
343342
344343
345−optimizePotentialTailCall :: Cycle -> Can.Def -> Names.Tracker Opt.Def
346−optimizePotentialTailCall cycle def =
344+optimizePotentialTailCallDef :: Cycle -> Can.Def -> Names.Tracker Opt.Def
345+optimizePotentialTailCallDef cycle def =
347346 case def of
348347 Can.Def (A.At _ name) args expr ->
349− do (argNames, destructors) <- destructArgs args
350− toTailDef name argNames destructors <$>
351− optimizeTail cycle name argNames expr
348+ optimizePotentialTailCall cycle name args expr
352349
353350 Can.TypedDef (A.At _ name) _ typedArgs expr _ ->
354− do (argNames, destructors) <- destructArgs (map fst typedArgs)
355− toTailDef name argNames destructors <$>
356− optimizeTail cycle name argNames expr
351+ optimizePotentialTailCall cycle name (map fst typedArgs) expr
352+
353+
354+optimizePotentialTailCall :: Cycle -> N.Name -> [Can.Pattern] -> Can.Expr -> Names.Tracker Opt.Def
355+optimizePotentialTailCall cycle name args expr =
356+ do (argNames, destructors) <- destructArgs args
357+ toTailDef name argNames destructors <$>
358+ optimizeTail cycle name argNames expr
357359
358360
359361optimizeTail :: Cycle -> N.Name -> [N.Name] -> Can.Expr -> Names.Tracker Opt.Expr
@@ -392,7 +394,7 @@ optimizeTail cycle rootName argNames locExpr@(A.At _ expression) =
392394 case defs of
393395 [def] ->
394396 Opt.Let
395− <$> optimizePotentialTailCall cycle def
397+ <$> optimizePotentialTailCallDef cycle def
396398 <*> optimizeTail cycle rootName argNames body
397399
398400 _ ->
compiler/src/Optimize/Module.hs+39−47
@@ -301,74 +301,66 @@ addDefNode home name args body mainDeps graph =
301301data State =
302302 State
303303 { _values :: [(N.Name, Opt.Expr)]
304− , _graph :: Opt.Graph
304+ , _functions :: [Opt.Def]
305305 }
306306
307307
308308addRecDefs :: ModuleName.Canonical -> [Can.Def] -> Opt.Graph -> Opt.Graph
309−addRecDefs home defs graph =
309+addRecDefs home defs (Opt.Graph mains nodes fieldCounts) =
310310 let
311− cycleValues = foldr addValueName Set.empty defs
312− dummyName = Opt.Global home (N.toCompositeName (Set.toList cycleValues))
311+ valueNames = foldr addValueName [] defs
312+ cycleName = Opt.Global home (N.toCompositeName valueNames)
313+ cycle = Set.fromList valueNames
314+ links = foldr (addLink home (Opt.Link cycleName)) Map.empty defs
313315
314− (deps, fields, State cyclicValuePairs newGraph) =
316+ (deps, fields, State values funcs) =
315317 Names.run $
316− foldM (addRecDef home dummyName cycleValues) (State [] graph) defs
318+ foldM (addRecDef cycle) (State [] []) defs
317319 in
318− addToGraph dummyName (Opt.Cycle cyclicValuePairs deps) fields newGraph
320+ Opt.Graph
321+ mains
322+ (Map.insert cycleName (Opt.Cycle values funcs deps) (Map.union links nodes))
323+ (Map.unionWith (+) fields fieldCounts)
319324
320325
321−addValueName :: Can.Def -> Set.Set N.Name -> Set.Set N.Name
322−addValueName def valueNames =
326+addValueName :: Can.Def -> [N.Name] -> [N.Name]
327+addValueName def names =
323328 case def of
324− Can.Def (A.At _ name) [] _ ->
325− Set.insert name valueNames
329+ Can.Def (A.At _ name) args _ -> if null args then name:names else names
330+ Can.TypedDef (A.At _ name) _ args _ _ -> if null args then name:names else names
326331
327− Can.TypedDef (A.At _ name) _ [] _ _ ->
328− Set.insert name valueNames
329332
330− _ ->
331− valueNames
333+addLink :: ModuleName.Canonical -> Opt.Node -> Can.Def -> Map.Map Opt.Global Opt.Node -> Map.Map Opt.Global Opt.Node
334+addLink home link def links =
335+ case def of
336+ Can.Def (A.At _ name) _ _ ->
337+ Map.insert (Opt.Global home name) link links
338+
339+ Can.TypedDef (A.At _ name) _ _ _ _ ->
340+ Map.insert (Opt.Global home name) link links
332341
333342
334343
335344-- ADD RECURSIVE DEFS
336345
337346
338−addRecDef :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> State -> Can.Def -> Names.Tracker State
339−addRecDef home dummyName cycle state@(State values graph) def =
347+addRecDef :: Set.Set N.Name -> State -> Can.Def -> Names.Tracker State
348+addRecDef cycle state def =
340349 case def of
341− Can.Def (A.At _ name) [] body ->
342− addRecValue home dummyName cycle name body state
350+ Can.Def (A.At _ name) args body ->
351+ addRecDefHelp cycle state name args body
343352
344− Can.TypedDef (A.At _ name) _ [] body _ ->
345− addRecValue home dummyName cycle name body state
353+ Can.TypedDef (A.At _ name) _ args body _ ->
354+ addRecDefHelp cycle state name (map fst args) body
346355
347− _ ->
348− let
349− (deps, fields, odef) =
350− Names.run (Expr.optimizePotentialTailCall cycle def)
351− in
352− pure $ State values $
353− case odef of
354− Opt.Def name body ->
355− let node = Opt.Define body deps in
356− addToGraph (Opt.Global home name) node fields graph
357−
358− Opt.TailDef name args body ->
359− let node = Opt.DefineTailFunc args body deps in
360− addToGraph (Opt.Global home name) node fields graph
361356
357+addRecDefHelp :: Set.Set N.Name -> State -> N.Name -> [Can.Pattern] -> Can.Expr -> Names.Tracker State
358+addRecDefHelp cycle (State values funcs) name args body =
359+ case args of
360+ [] ->
361+ do obody <- Expr.optimize cycle body
362+ pure $ State ((name, obody) : values) funcs
362363
363−addRecValue :: ModuleName.Canonical -> Opt.Global -> Expr.Cycle -> N.Name -> Can.Expr -> State -> Names.Tracker State
364−addRecValue home dummyName cycle name body (State values (Opt.Graph mains nodes fields)) =
365− do obody <- Expr.optimize cycle body
366−
367− let global = Opt.Global home name
368− let node = Opt.Link dummyName
369−
370− pure $
371− State
372− { _values = (name, obody) : values
373− , _graph = Opt.Graph mains (Map.insert global node nodes) fields
374− }
364+ _:_ ->
365+ do odef <- Expr.optimizePotentialTailCall cycle name args body
366+ pure $ State values (odef : funcs)