1{-# OPTIONS_GHC -Wall #-}
2module Transform.SortDefinitions (sortDefs) where
4import Control.Monad.State
5import Control.Applicative ((<$>),(<*>))
6import qualified Data.Graph as Graph
7import qualified Data.Map as Map
8import qualified Data.Maybe as Maybe
9import qualified Data.Set as Set
12import AST.Expression.General (Expr'(..))
13import qualified AST.Expression.Canonical as Canonical
14import qualified AST.Pattern as P
15import qualified AST.Variable as V
18ctors :: P.CanonicalPattern -> [String]
22 P.Alias _ p -> ctors p
26 P.Data (V.Canonical home name) ps ->
28 V.Local -> name : rest
32 rest = concatMap ctors ps
35free :: String -> State (Set.Set String) ()
40freeIfLocal :: V.Canonical -> State (Set.Set String) ()
41freeIfLocal (V.Canonical home name) =
44 V.BuiltIn -> return ()
45 V.Module _ -> return ()
48bound :: Set.Set String -> State (Set.Set String) ()
50 modify (\freeVars -> Set.difference freeVars boundVars)
53sortDefs :: Canonical.Expr -> Canonical.Expr
55 evalState (reorder expression) Set.empty
58reorder :: Canonical.Expr -> State (Set.Set String) Canonical.Expr
59reorder (A ann expression) =
62 -- Be careful adding and restricting freeVars
67 Lambda pattern body ->
68 uncurry Lambda <$> bindingReorder (pattern,body)
70 Binop op leftExpr rightExpr ->
72 Binop op <$> reorder leftExpr <*> reorder rightExpr
75 Case <$> reorder expr <*> mapM bindingReorder cases
79 Data name <$> mapM reorder exprs
81 -- Just pipe the reorder though
85 Range lowExpr highExpr ->
86 Range <$> reorder lowExpr <*> reorder highExpr
89 ExplicitList <$> mapM reorder es
92 App <$> reorder func <*> reorder arg
95 MultiIf <$> mapM (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
97 Access record field ->
98 Access <$> reorder record <*> return field
100 Remove record field ->
101 Remove <$> reorder record <*> return field
103 Insert record field expr ->
104 Insert <$> reorder record <*> return field <*> reorder expr
106 Modify record fields ->
109 <*> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
113 <$> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
119 return $ Port name impl
121 -- Actually do some reordering
123 do body' <- reorder body
125 -- Sort defs into strongly connected components.This
126 -- allows the programmer to write definitions in whatever
127 -- order they please, we can still define things in order
128 -- and generalize polymorphic functions when appropriate.
129 sccs <- Graph.stronglyConnComp <$> buildDefDict defs
130 let defss = map Graph.flattenSCC sccs
132 -- remove let-bound variables from the context
133 forM_ defs $ \(Canonical.Definition pattern _ _) -> do
134 bound (P.boundVars pattern)
135 mapM free (ctors pattern)
138 foldr (\ds bod -> A ann (Let ds bod)) body' defss
144 :: (P.CanonicalPattern, Canonical.Expr)
145 -> State (Set.Set String) (P.CanonicalPattern, Canonical.Expr)
146bindingReorder (pattern,expr) =
147 do expr' <- reorder expr
148 bound (P.boundVars pattern)
149 mapM_ free (ctors pattern)
150 return (pattern, expr')
153reorderAndGetDependencies
155 -> State (Set.Set String) (Canonical.Def, [String])
156reorderAndGetDependencies (Canonical.Definition pattern expr mType) =
157 do globalFrees <- get
158 -- work in a fresh environment
160 expr' <- reorder expr
162 -- merge with global frees
163 modify (Set.union globalFrees)
164 return (Canonical.Definition pattern expr' mType, Set.toList localFrees)
167-- This also reorders the all of the sub-expressions in the Def list.
170 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
172 do pdefsDeps <- mapM reorderAndGetDependencies defs
173 return $ realDeps (addKey pdefsDeps)
175 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
177 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
179 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
180 variableToKey (Canonical.Definition pattern _ _, key, _) =
181 [ (var, key) | var <- Set.toList (P.boundVars pattern) ]
183 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
184 variableToKeyMap pdefsDeps =
185 Map.fromList (concatMap variableToKey pdefsDeps)
187 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
189 map convert pdefsDeps
191 varDict = variableToKeyMap pdefsDeps
192 convert (pdef, key, deps) =
193 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
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