@@ -1,7 +1,7 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Sort (definitions) where
2module Canonicalize.Sort (definitions) where
4−import Control.Monad.State
4+import qualified Data.Foldable as F
5import qualified Data.Graph as Graph
5import qualified Data.Graph as Graph
6import qualified Data.Map as Map
6import qualified Data.Map as Map
7import qualified Data.Maybe as Maybe
7import qualified Data.Maybe as Maybe
@@ -12,71 +12,117 @@ import qualified AST.Expression.Canonical as Canonical
12import qualified AST.Pattern as P
12import qualified AST.Pattern as P
13import qualified AST.Variable as V
13import qualified AST.Variable as V
14import qualified Reporting.Annotation as A
14import qualified Reporting.Annotation as A
15+import qualified Reporting.Error.Canonicalize as E
16+import qualified Reporting.Result as R
18−-- STARTING POINT
20+-- SORT DEFINITIONS
21−definitions :: Canonical.Expr -> Canonical.Expr
23+definitions :: (Monoid i) => Canonical.Expr -> R.Result i w E.Error Canonical.Expr
22definitions expression =
24definitions expression =
26+ (R.Result _ warnings answer) =
23− evalState (reorder expression) Set.empty
27+ reorder expression
29+ R.Result mempty warnings answer
34+ { _immediate :: Set.Set String
35+ , _delayed :: Set.Set String
36+ , _tags :: Set.Set String
40+instance Monoid LocalVars where
42+ LocalVars Set.empty Set.empty Set.empty
26−free :: String -> State (Set.Set String) ()
44+ mappend (LocalVars i1 d1 t1) (LocalVars i2 d2 t2) =
27−free x =
45+ LocalVars (Set.union i1 i2) (Set.union d1 d2) (Set.union t1 t2)
28− modify (Set.insert x)
31−freeIfLocal :: V.Canonical -> State (Set.Set String) ()
48+addTag :: String -> a -> R.Result LocalVars w e a
50+ R.accumulate (LocalVars Set.empty Set.empty (Set.singleton name)) value
53+addImmediate :: V.Canonical -> a -> R.Result LocalVars w e a
32−freeIfLocal (V.Canonical home name) =
54+addImmediate (V.Canonical home name) value =
33 case home of
55 case home of
34− V.Local -> free name
56+ V.Local ->
57+ R.accumulate (LocalVars (Set.singleton name) Set.empty Set.empty) value
35− V.TopLevel _ -> free name
59+ V.TopLevel _ ->
60+ R.accumulate (LocalVars (Set.singleton name) Set.empty Set.empty) value
36− V.BuiltIn -> return ()
62+ V.BuiltIn ->
37− V.Module _ -> return ()
65+ V.Module _ ->
69+capture :: P.Canonical -> R.Result LocalVars w e a -> R.Result LocalVars w e a
70+capture pattern result =
71+ captureVars (P.boundVarSet pattern) result
74+captureVars :: Set.Set String -> R.Result LocalVars w e a -> R.Result LocalVars w e a
75+captureVars bound (R.Result (LocalVars immediate delayed tags) warnings result) =
78+ LocalVars (Set.difference immediate bound) (Set.difference delayed bound) tags
80+ R.Result localVars warnings result
83+delay :: R.Result LocalVars w e a -> R.Result LocalVars w e a
84+delay (R.Result (LocalVars immediate delayed tags) warnings result) =
85+ R.Result (LocalVars Set.empty (Set.union immediate delayed) tags) warnings result
41-- REORDER EXPRESSIONS
89-- REORDER EXPRESSIONS
44−reorder :: Canonical.Expr -> State (Set.Set String) Canonical.Expr
92+reorder :: Canonical.Expr -> R.Result LocalVars w E.Error Canonical.Expr
45−reorder (A.A ann expression) =
93+reorder (A.A region expression) =
46− A.A ann <$>
94+ A.A region <$>
47 case expression of
95 case expression of
48− -- Be careful adding and restricting freeVars
49 Var var ->
96 Var var ->
51− return expression
97+ addImmediate var expression
53 Lambda pattern body ->
99 Lambda pattern body ->
54− uncurry Lambda <$> bindingReorder (pattern,body)
101+ bindingReorder Lambda (pattern, body)
56 Binop op leftExpr rightExpr ->
103 Binop op leftExpr rightExpr ->
58− Binop op <$> reorder leftExpr <*> reorder rightExpr
104+ do binop <- Binop op <$> reorder leftExpr <*> reorder rightExpr
105+ addImmediate op binop
60 Case expr cases ->
107 Case expr cases ->
61− Case <$> reorder expr <*> mapM bindingReorder cases
108+ Case <$> reorder expr <*> traverse (bindingReorder (,)) cases
63 Data name exprs ->
110 Data name exprs ->
65− Data name <$> mapM reorder exprs
111+ addTag name =<< (Data name <$> traverse reorder exprs)
67 -- Just pipe the reorder though
113 -- Just pipe the reorder though
68 Literal _ ->
114 Literal _ ->
69 return expression
115 return expression
71 ExplicitList es ->
117 ExplicitList es ->
72− ExplicitList <$> mapM reorder es
118+ ExplicitList <$> traverse reorder es
74 App func arg ->
120 App func arg ->
75 App <$> reorder func <*> reorder arg
121 App <$> reorder func <*> reorder arg
77 If branches finally ->
123 If branches finally ->
79− <$> mapM (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
125+ <$> traverse (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
80 <*> reorder finally
126 <*> reorder finally
82 Access record field ->
128 Access record field ->
@@ -87,11 +133,11 @@ reorder (A.A ann expression) =
87 Update record fields ->
133 Update record fields ->
89 <$> reorder record
135 <$> reorder record
90− <*> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
136+ <*> traverse (traverse reorder) fields
92 Record fields ->
138 Record fields ->
94− <$> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
140+ <$> traverse (traverse reorder) fields
97 return expression
143 return expression
@@ -116,117 +162,185 @@ reorder (A.A ann expression) =
117 -- Actually do some reordering
163 -- Actually do some reordering
118 Let defs body ->
164 Let defs body ->
119− do body' <- reorder body
165+ case reorderDefs defs of
166+ R.Result () warnings (R.Err errors) ->
167+ R.Result mempty warnings (R.Err errors)
169+ R.Result () warnings (R.Ok (boundVars, defGroups, defLocals)) ->
170+ captureVars boundVars $
171+ do _ <- R.Result mempty warnings (R.Ok ())
172+ newBody <- reorder body
173+ R.accumulate defLocals $ A.drop $
174+ foldr (\defGroup expr -> A.A region (Let defGroup expr)) newBody defGroups
182+ :: (P.Canonical -> Canonical.Expr -> a)
183+ -> (P.Canonical, Canonical.Expr)
184+ -> R.Result LocalVars w E.Error a
185+bindingReorder func (pattern, expr) =
186+ do answer <- func pattern <$> capture pattern (reorder expr)
187+ addPatternTags pattern answer
121− -- Sort defs into strongly connected components.This
122− -- allows the programmer to write definitions in whatever
123− -- order they please, we can still define things in order
124− -- and generalize polymorphic functions when appropriate.
125− sccs <- Graph.stronglyConnComp <$> buildDefGraph defs
126− let defss = map Graph.flattenSCC sccs
128− -- remove let-bound variables from the context
129− forM_ defs $ \(Canonical.Def _ pattern _ _) -> do
131− mapM free (ctors pattern)
133− let (A.A _ let') =
191+-- FREE CONSTRUCTORS
134− foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
194+addPatternTags :: P.Canonical -> a -> R.Result LocalVars w e a
195+addPatternTags pattern value =
196+ R.accumulate (LocalVars Set.empty Set.empty (getPatternTags pattern)) value
139−ctors :: P.Canonical -> [String]
199+getPatternTags :: P.Canonical -> Set.Set String
140−ctors (A.A _ pattern) =
200+getPatternTags (A.A _ pattern) =
141 case pattern of
201 case pattern of
142 P.Var _ ->
202 P.Var _ ->
145− P.Alias _ p ->
205+ P.Alias _ subPattern ->
146− ctors p
206+ getPatternTags subPattern
148 P.Record _ ->
208 P.Record _ ->
151 P.Anything ->
211 P.Anything ->
154 P.Literal _ ->
214 P.Literal _ ->
157− P.Data (V.Canonical home name) ps ->
217+ P.Data (V.Canonical home name) patterns ->
220+ Set.unions (map getPatternTags patterns)
158 case home of
222 case home of
159− V.Local -> name : rest
223+ V.Local ->
224+ Set.insert name freeCtors
160− V.TopLevel _ -> name : rest
226+ V.TopLevel _ ->
227+ Set.insert name freeCtors
161− V.BuiltIn -> rest
229+ V.BuiltIn ->
162− V.Module _ -> rest
232+ V.Module _ ->
164− rest = concatMap ctors ps
234+
237+-- REORDER DEFINITIONS
242+ -> R.Result () w E.Error (Set.Set String, [[Canonical.Def]], LocalVars)
244+ do rawNodes <- sequenceA $ zipWith toRawNode [0..] defs
245+ let boundVarDict = toBoundVarDict rawNodes
246+ _ <- detectLoops boundVarDict rawNodes
247+ return $ groupDefs boundVarDict rawNodes
167−bound :: P.Canonical -> State (Set.Set String) ()
249+
168−bound pattern =
250+toRawNode :: Int -> Canonical.Def -> R.Result () w E.Error (Canonical.Def, Int, LocalVars)
251+toRawNode index (Canonical.Def region pattern body maybeType) =
170− boundVars =
253+ (R.Result localVars warnings answer) =
171− P.boundVarSet pattern
254+ addPatternTags pattern =<< reorder body
256+ toRawNodeHelp newBody =
257+ ( Canonical.Def region pattern newBody maybeType, index, localVars )
173− modify (\freeVars -> Set.difference freeVars boundVars)
259+ toRawNodeHelp <$> R.Result () warnings answer
176−bindingReorder
262+toBoundVarDict :: [(Canonical.Def, Int, a)] -> Map.Map String Int
177− :: (P.Canonical, Canonical.Expr)
263+toBoundVarDict defAndDeps =
178− -> State (Set.Set String) (P.Canonical, Canonical.Expr)
179−bindingReorder (pattern, expr) =
180− do expr' <- reorder expr
182− mapM_ free (ctors pattern)
183− return (pattern, expr')
187−-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
190−-- This also reorders the all of the sub-expressions in the Def list.
193− -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
195− do pdefsDeps <- mapM reorderAndGetDependencies defs
196− return $ realDeps (addKey pdefsDeps)
198− addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
200− zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
202− variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
203− variableToKey (Canonical.Def _ pattern _ _, key, _) =
204− [ (var, key) | var <- P.boundVarList pattern ]
206− variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
207− variableToKeyMap pdefsDeps =
208− Map.fromList (concatMap variableToKey pdefsDeps)
264+ Map.fromList (concatMap toBoundVarDictHelp defAndDeps)
210− realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
267+toBoundVarDictHelp :: (Canonical.Def, Int, a) -> [(String, Int)]
211− realDeps pdefsDeps =
268+toBoundVarDictHelp (Canonical.Def _ pattern _ _, key, _) =
212− map convert pdefsDeps
269+ map (\(A.A _ name) -> (name, key)) (P.boundVars pattern)
215− variableToKeyMap pdefsDeps
272+
217− convert (pdef, key, deps) =
274+
277+ :: (deps -> [String])
278+ -> Map.Map String Int
279+ -> (Canonical.Def, Int, deps)
280+ -> (Canonical.Def, Int, [Int])
281+toNode toVars boundVarDict (def, index, deps) =
218− (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
284+ Maybe.mapMaybe (\var -> Map.lookup var boundVarDict) (toVars deps)
220−
286+ ( def, index, localDeps )
221−reorderAndGetDependencies
287+
222− :: Canonical.Def
288+
289+immediateOnly :: LocalVars -> [String]
290+immediateOnly (LocalVars immediate _ _) =
291+ Set.toList immediate
294+allVars :: LocalVars -> [String]
295+allVars (LocalVars immediate delayed tags) =
296+ Set.toList immediate ++ Set.toList delayed ++ Set.toList tags
304+ :: Map.Map String Int
223− -> State (Set.Set String) (Canonical.Def, [String])
305+ -> [(Canonical.Def, Int, LocalVars)]
224−reorderAndGetDependencies (Canonical.Def facts pattern expr mType) =
306+ -> R.Result () w E.Error ()
225− do globalFrees <- get
307+detectLoops boundVarDict rawNodes =
226− -- work in a fresh environment
308+ F.traverse_ detectLoopsHelp $
227− put Set.empty
309+ Graph.stronglyConnComp $
228− expr' <- reorder expr
310+ map (toNode immediateOnly boundVarDict) rawNodes
229− localFrees <- get
311+
230− -- merge with global frees
312+
231− modify (Set.union globalFrees)
313+detectLoopsHelp :: Graph.SCC Canonical.Def -> R.Result () w E.Error ()
232− return (Canonical.Def facts pattern expr' mType, Set.toList localFrees)
314+detectLoopsHelp scc =
316+ Graph.AcyclicSCC _ ->
319+ Graph.CyclicSCC defs ->
324+ def@(Canonical.Def region (A.A nameRegion _) _ _) : rest ->
325+ R.throw region $ E.BadRecursion nameRegion def rest
333+ :: Map.Map String Int
334+ -> [(Canonical.Def, Int, LocalVars)]
335+ -> ( Set.Set String, [[Canonical.Def]], LocalVars )
336+groupDefs boundVarDict rawNodes =
339+ mconcat (map (\(_, _, localVars) -> localVars) rawNodes)
342+ map Graph.flattenSCC $
343+ Graph.stronglyConnComp $
344+ map (toNode allVars boundVarDict) rawNodes
346+ ( Map.keysSet boundVarDict, defGroups, allLocalVars )