1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Sort (definitions) where
4import Control.Monad.State
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
21definitions :: Canonical.Expr -> Canonical.Expr
22definitions expression =
23 evalState (reorder expression) Set.empty
26free :: String -> State (Set.Set String) ()
31freeIfLocal :: V.Canonical -> State (Set.Set String) ()
32freeIfLocal (V.Canonical home name) =
35 V.TopLevel _ -> free name
36 V.BuiltIn -> return ()
37 V.Module _ -> return ()
44reorder :: Canonical.Expr -> State (Set.Set String) Canonical.Expr
45reorder (A.A ann expression) =
48 -- Be careful adding and restricting freeVars
53 Lambda pattern body ->
54 uncurry Lambda <$> bindingReorder (pattern,body)
56 Binop op leftExpr rightExpr ->
58 Binop op <$> reorder leftExpr <*> reorder rightExpr
61 Case <$> reorder expr <*> mapM bindingReorder cases
65 Data name <$> mapM reorder exprs
67 -- Just pipe the reorder though
71 Range lowExpr highExpr ->
72 Range <$> reorder lowExpr <*> reorder highExpr
75 ExplicitList <$> mapM reorder es
78 App <$> reorder func <*> reorder arg
80 If branches finally ->
82 <$> mapM (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
85 Access record field ->
90 Update record fields ->
93 <*> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
97 <$> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
108 -- Actually do some reordering
110 do body' <- reorder body
112 -- Sort defs into strongly connected components.This
113 -- allows the programmer to write definitions in whatever
114 -- order they please, we can still define things in order
115 -- and generalize polymorphic functions when appropriate.
116 sccs <- Graph.stronglyConnComp <$> buildDefGraph defs
117 let defss = map Graph.flattenSCC sccs
119 -- remove let-bound variables from the context
120 forM_ defs $ \(Canonical.Definition _ pattern _ _) -> do
122 mapM free (ctors pattern)
125 foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
130ctors :: P.Canonical -> [String]
131ctors (A.A _ pattern) =
148 P.Data (V.Canonical home name) ps ->
150 V.Local -> name : rest
151 V.TopLevel _ -> name : rest
155 rest = concatMap ctors ps
158bound :: P.Canonical -> State (Set.Set String) ()
162 P.boundVarSet pattern
164 modify (\freeVars -> Set.difference freeVars boundVars)
168 :: (P.Canonical, Canonical.Expr)
169 -> State (Set.Set String) (P.Canonical, Canonical.Expr)
170bindingReorder (pattern, expr) =
171 do expr' <- reorder expr
173 mapM_ free (ctors pattern)
174 return (pattern, expr')
178-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
181-- This also reorders the all of the sub-expressions in the Def list.
184 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
186 do pdefsDeps <- mapM reorderAndGetDependencies defs
187 return $ realDeps (addKey pdefsDeps)
189 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
191 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
193 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
194 variableToKey (Canonical.Definition _ pattern _ _, key, _) =
195 [ (var, key) | var <- P.boundVarList pattern ]
197 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
198 variableToKeyMap pdefsDeps =
199 Map.fromList (concatMap variableToKey pdefsDeps)
201 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
203 map convert pdefsDeps
206 variableToKeyMap pdefsDeps
208 convert (pdef, key, deps) =
209 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
212reorderAndGetDependencies
214 -> State (Set.Set String) (Canonical.Def, [String])
215reorderAndGetDependencies (Canonical.Definition facts pattern expr mType) =
216 do globalFrees <- get
217 -- work in a fresh environment
219 expr' <- reorder expr
221 -- merge with global frees
222 modify (Set.union globalFrees)
223 return (Canonical.Definition facts pattern expr' mType, Set.toList localFrees)
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