1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Sort (definitions) where
4import qualified Data.Foldable as F
5import qualified Data.Graph as Graph
6import qualified Data.Map as Map
7import qualified Data.Maybe as Maybe
8import qualified Data.Set as Set
11import qualified AST.Expression.Canonical as C
12import qualified AST.Pattern as P
13import qualified AST.Variable as V
14import qualified Reporting.Annotation as A
15import qualified Reporting.Error.Canonicalize as E
16import qualified Reporting.Result as R
23definitions :: (Monoid i) => C.Expr -> R.Result i w E.Error C.Expr
24definitions expression =
26 (R.Result _ warnings answer) =
29 R.Result mempty warnings answer
34 { _immediate :: Set.Set Text
35 , _delayed :: Set.Set Text
36 , _tags :: Set.Set Text
40instance Monoid LocalVars where
42 LocalVars Set.empty Set.empty Set.empty
44 mappend (LocalVars i1 d1 t1) (LocalVars i2 d2 t2) =
45 LocalVars (Set.union i1 i2) (Set.union d1 d2) (Set.union t1 t2)
48addTag :: Text -> a -> R.Result LocalVars w e a
50 R.accumulate (LocalVars Set.empty Set.empty (Set.singleton name)) value
53addImmediate :: V.Canonical -> a -> R.Result LocalVars w e a
54addImmediate (V.Canonical home name) value =
57 R.accumulate (LocalVars (Set.singleton name) Set.empty Set.empty) value
60 R.accumulate (LocalVars (Set.singleton name) Set.empty Set.empty) value
69capture :: P.Canonical -> R.Result LocalVars w e a -> R.Result LocalVars w e a
70capture pattern result =
71 captureVars (P.boundVarSet pattern) result
74captureVars :: Set.Set Text -> R.Result LocalVars w e a -> R.Result LocalVars w e a
75captureVars 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
83delay :: R.Result LocalVars w e a -> R.Result LocalVars w e a
84delay (R.Result (LocalVars immediate delayed tags) warnings result) =
85 R.Result (LocalVars Set.empty (Set.union immediate delayed) tags) warnings result
92reorder :: C.Expr -> R.Result LocalVars w E.Error C.Expr
93reorder (A.A region expression) =
97 addImmediate var expression
99 C.Lambda pattern body ->
101 bindingReorder C.Lambda (pattern, body)
103 C.Binop op leftExpr rightExpr ->
104 do binop <- C.Binop op <$> reorder leftExpr <*> reorder rightExpr
105 addImmediate op binop
108 C.Case <$> reorder expr <*> traverse (bindingReorder (,)) cases
110 C.Ctor ctor@(V.Canonical _ name) exprs ->
111 addTag name =<< (C.Ctor ctor <$> traverse reorder exprs)
113 -- Just pipe the reorder though
118 C.List <$> traverse reorder es
121 C.App <$> reorder func <*> reorder arg
123 C.If branches finally ->
125 <$> traverse (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
128 C.Access record field ->
133 C.Update record fields ->
136 <*> traverse (traverse reorder) fields
140 <$> traverse (traverse reorder) fields
148 C.OutgoingPort _ _ ->
151 C.IncomingPort _ _ ->
155 error "DANGER - Program AST nodes should not be in def sorting."
163 -- Actually do some reordering
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 (C.Let defGroup expr)) newBody defGroups
182 :: (P.Canonical -> C.Expr -> a)
183 -> (P.Canonical, C.Expr)
184 -> R.Result LocalVars w E.Error a
185bindingReorder func (pattern, expr) =
186 do answer <- func pattern <$> capture pattern (reorder expr)
187 addPatternTags pattern answer
194addPatternTags :: P.Canonical -> a -> R.Result LocalVars w e a
195addPatternTags pattern value =
196 R.accumulate (LocalVars Set.empty Set.empty (getPatternTags pattern)) value
199getPatternTags :: P.Canonical -> Set.Set Text
200getPatternTags (A.A _ pattern) =
205 P.Alias _ subPattern ->
206 getPatternTags subPattern
217 P.Ctor (V.Canonical home name) patterns ->
220 Set.unions (map getPatternTags patterns)
224 Set.insert name freeCtors
227 Set.insert name freeCtors
237-- REORDER DEFINITIONS
242 -> R.Result () w E.Error (Set.Set Text, [[C.Def]], LocalVars)
244 do rawNodes <- sequenceA $ zipWith toRawNode [0..] defs
245 let boundVarDict = toBoundVarDict rawNodes
246 _ <- detectLoops boundVarDict rawNodes
247 return $ groupDefs boundVarDict rawNodes
250toRawNode :: Int -> C.Def -> R.Result () w E.Error (C.Def, Int, LocalVars)
251toRawNode index (C.Def region pattern body maybeType) =
253 (R.Result localVars warnings answer) =
254 addPatternTags pattern =<< reorder body
256 toRawNodeHelp newBody =
257 ( C.Def region pattern newBody maybeType, index, localVars )
259 toRawNodeHelp <$> R.Result () warnings answer
262toBoundVarDict :: [(C.Def, Int, a)] -> Map.Map Text Int
263toBoundVarDict defAndDeps =
264 Map.fromList (concatMap toBoundVarDictHelp defAndDeps)
267toBoundVarDictHelp :: (C.Def, Int, a) -> [(Text, Int)]
268toBoundVarDictHelp (C.Def _ pattern _ _, key, _) =
269 map (\(A.A _ name) -> (name, key)) (P.boundVars pattern)
279 -> (C.Def, Int, deps)
280 -> (C.Def, Int, [Int])
281toNode toVars boundVarDict (def, index, deps) =
284 Maybe.mapMaybe (\var -> Map.lookup var boundVarDict) (toVars deps)
286 ( def, index, localDeps )
289immediateOnly :: LocalVars -> [Text]
290immediateOnly (LocalVars immediate _ _) =
294allVars :: LocalVars -> [Text]
295allVars (LocalVars immediate delayed tags) =
296 Set.toList immediate ++ Set.toList delayed ++ Set.toList tags
305 -> [(C.Def, Int, LocalVars)]
306 -> R.Result () w E.Error ()
307detectLoops boundVarDict rawNodes =
308 F.traverse_ detectLoopsHelp $
309 Graph.stronglyConnComp $
310 map (toNode immediateOnly boundVarDict) rawNodes
313detectLoopsHelp :: Graph.SCC C.Def -> R.Result () w E.Error ()
316 Graph.AcyclicSCC _ ->
319 Graph.CyclicSCC defs ->
324 def@(C.Def region (A.A nameRegion _) _ _) : rest ->
325 R.throw region $ E.BadRecursion nameRegion def rest
334 -> [(C.Def, Int, LocalVars)]
335 -> ( Set.Set Text, [[C.Def]], LocalVars )
336groupDefs 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 )
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list