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
10import AST.Expression.General (Expr'(..))
11import qualified AST.Expression.Canonical as Canonical
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) => Canonical.Expr -> R.Result i w E.Error Canonical.Expr
24definitions expression =
26 (R.Result _ warnings answer) =
29 R.Result mempty warnings answer
34 { _immediate :: Set.Set String
35 , _delayed :: Set.Set String
36 , _tags :: Set.Set String
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 :: String -> 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 String -> 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 :: Canonical.Expr -> R.Result LocalVars w E.Error Canonical.Expr
93reorder (A.A region expression) =
97 addImmediate var expression
99 Lambda pattern body ->
101 bindingReorder Lambda (pattern, body)
103 Binop op leftExpr rightExpr ->
104 do binop <- Binop op <$> reorder leftExpr <*> reorder rightExpr
105 addImmediate op binop
108 Case <$> reorder expr <*> traverse (bindingReorder (,)) cases
111 addTag name =<< (Data name <$> traverse reorder exprs)
113 -- Just pipe the reorder though
118 ExplicitList <$> traverse reorder es
121 App <$> reorder func <*> reorder arg
123 If branches finally ->
125 <$> traverse (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
128 Access record field ->
133 Update record fields ->
136 <*> traverse (traverse reorder) fields
140 <$> traverse (traverse reorder) fields
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 (Let defGroup expr)) newBody defGroups
182 :: (P.Canonical -> Canonical.Expr -> a)
183 -> (P.Canonical, Canonical.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 String
200getPatternTags (A.A _ pattern) =
205 P.Alias _ subPattern ->
206 getPatternTags subPattern
217 P.Data (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 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
250toRawNode :: Int -> Canonical.Def -> R.Result () w E.Error (Canonical.Def, Int, LocalVars)
251toRawNode index (Canonical.Def region pattern body maybeType) =
253 (R.Result localVars warnings answer) =
254 addPatternTags pattern =<< reorder body
256 toRawNodeHelp newBody =
257 ( Canonical.Def region pattern newBody maybeType, index, localVars )
259 toRawNodeHelp <$> R.Result () warnings answer
262toBoundVarDict :: [(Canonical.Def, Int, a)] -> Map.Map String Int
263toBoundVarDict defAndDeps =
264 Map.fromList (concatMap toBoundVarDictHelp defAndDeps)
267toBoundVarDictHelp :: (Canonical.Def, Int, a) -> [(String, Int)]
268toBoundVarDictHelp (Canonical.Def _ pattern _ _, key, _) =
269 map (\(A.A _ name) -> (name, key)) (P.boundVars pattern)
277 :: (deps -> [String])
278 -> Map.Map String Int
279 -> (Canonical.Def, Int, deps)
280 -> (Canonical.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 -> [String]
290immediateOnly (LocalVars immediate _ _) =
294allVars :: LocalVars -> [String]
295allVars (LocalVars immediate delayed tags) =
296 Set.toList immediate ++ Set.toList delayed ++ Set.toList tags
304 :: Map.Map String Int
305 -> [(Canonical.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 Canonical.Def -> R.Result () w E.Error ()
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 )
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