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
115 return $ Input name st
117 Output name st signal ->
118 Output name st <$> reorder signal
120 Loopback name st maybeExpr ->
122 maybe (return Nothing) (fmap Just . reorder) maybeExpr
124 -- Actually do some reordering
126 do body' <- reorder body
128 -- Sort defs into strongly connected components.This
129 -- allows the programmer to write definitions in whatever
130 -- order they please, we can still define things in order
131 -- and generalize polymorphic functions when appropriate.
132 sccs <- Graph.stronglyConnComp <$> buildDefDict defs
133 let defss = map Graph.flattenSCC sccs
135 -- remove let-bound variables from the context
136 forM_ defs $ \(Canonical.Definition pattern _ _) -> do
137 bound (P.boundVars pattern)
138 mapM free (ctors pattern)
141 foldr (\ds bod -> A ann (Let ds bod)) body' defss
147 :: (P.CanonicalPattern, Canonical.Expr)
148 -> State (Set.Set String) (P.CanonicalPattern, Canonical.Expr)
149bindingReorder (pattern,expr) =
150 do expr' <- reorder expr
151 bound (P.boundVars pattern)
152 mapM_ free (ctors pattern)
153 return (pattern, expr')
156reorderAndGetDependencies
158 -> State (Set.Set String) (Canonical.Def, [String])
159reorderAndGetDependencies (Canonical.Definition pattern expr mType) =
160 do globalFrees <- get
161 -- work in a fresh environment
163 expr' <- reorder expr
165 -- merge with global frees
166 modify (Set.union globalFrees)
167 return (Canonical.Definition pattern expr' mType, Set.toList localFrees)
170-- This also reorders the all of the sub-expressions in the Def list.
173 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
175 do pdefsDeps <- mapM reorderAndGetDependencies defs
176 return $ realDeps (addKey pdefsDeps)
178 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
180 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
182 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
183 variableToKey (Canonical.Definition pattern _ _, key, _) =
184 [ (var, key) | var <- Set.toList (P.boundVars pattern) ]
186 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
187 variableToKeyMap pdefsDeps =
188 Map.fromList (concatMap variableToKey pdefsDeps)
190 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
192 map convert pdefsDeps
194 varDict = variableToKeyMap pdefsDeps
195 convert (pdef, key, deps) =
196 (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