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 expr) Set.empty
58reorder :: Canonical.Expr -> State (Set.Set String) Canonical.Expr
62 -- Be careful adding and restricting freeVars
64 freeIfLocal var >> return expr
67 uncurry Lambda <$> bindingReorder (p,e)
71 Binop op <$> reorder e1 <*> reorder e2
74 Case <$> reorder e <*> mapM bindingReorder cases
78 Data name <$> mapM reorder es
80 -- Just pipe the reorder though
85 Range <$> reorder e1 <*> reorder e2
88 ExplicitList <$> mapM reorder es
91 App <$> reorder e1 <*> reorder e2
94 MultiIf <$> mapM (\(e1,e2) -> (,) <$> reorder e1 <*> reorder e2) branches
97 Access <$> reorder e <*> return lbl
100 Remove <$> reorder e <*> return lbl
103 Insert <$> reorder e <*> return lbl <*> reorder v
106 Modify <$> reorder e <*> mapM (\(k,v) -> (,) k <$> reorder v) fields
109 Record <$> mapM (\(k,v) -> (,) k <$> reorder v) fields
114 PortOut name st signal ->
115 PortOut name st <$> reorder signal
118 return $ PortIn name st
120 -- Actually do some reordering
122 do body' <- reorder body
124 -- Sort defs into strongly connected components.This
125 -- allows the programmer to write definitions in whatever
126 -- order they please, we can still define things in order
127 -- and generalize polymorphic functions when appropriate.
128 sccs <- Graph.stronglyConnComp <$> buildDefDict defs
129 let defss = map Graph.flattenSCC sccs
131 -- remove let-bound variables from the context
132 forM_ defs $ \(Canonical.Definition pattern _ _) -> do
133 bound (P.boundVars pattern)
134 mapM free (ctors pattern)
137 foldr (\ds bod -> A ann (Let ds bod)) body' defss
143 :: (P.CanonicalPattern, Canonical.Expr)
144 -> State (Set.Set String) (P.CanonicalPattern, Canonical.Expr)
145bindingReorder (pattern,expr) =
146 do expr' <- reorder expr
147 bound (P.boundVars pattern)
148 mapM_ free (ctors pattern)
149 return (pattern, expr')
152reorderAndGetDependencies
154 -> State (Set.Set String) (Canonical.Def, [String])
155reorderAndGetDependencies (Canonical.Definition pattern expr mType) =
156 do globalFrees <- get
157 -- work in a fresh environment
159 expr' <- reorder expr
161 -- merge with global frees
162 modify (Set.union globalFrees)
163 return (Canonical.Definition pattern expr' mType, Set.toList localFrees)
166-- This also reorders the all of the sub-expressions in the Def list.
169 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
171 do pdefsDeps <- mapM reorderAndGetDependencies defs
172 return $ realDeps (addKey pdefsDeps)
174 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
176 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
178 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
179 variableToKey (Canonical.Definition pattern _ _, key, _) =
180 [ (var, key) | var <- Set.toList (P.boundVars pattern) ]
182 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
183 variableToKeyMap pdefsDeps =
184 Map.fromList (concatMap variableToKey pdefsDeps)
186 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
188 map convert pdefsDeps
190 varDict = variableToKeyMap pdefsDeps
191 convert (pdef, key, deps) =
192 (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