1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Sort (definitions) 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
11import AST.Expression.General (Expr'(..), PortImpl(..))
12import qualified AST.Expression.Canonical as Canonical
13import qualified AST.Pattern as P
14import qualified AST.Variable as V
15import qualified Reporting.Annotation as A
20definitions :: Canonical.Expr -> Canonical.Expr
21definitions expression =
22 evalState (reorder expression) Set.empty
25free :: String -> State (Set.Set String) ()
30freeIfLocal :: V.Canonical -> State (Set.Set String) ()
31freeIfLocal (V.Canonical home name) =
34 V.TopLevel _ -> free name
35 V.BuiltIn -> return ()
36 V.Module _ -> return ()
41reorder :: Canonical.Expr -> State (Set.Set String) Canonical.Expr
42reorder (A.A ann expression) =
45 -- Be careful adding and restricting freeVars
50 Lambda pattern body ->
51 uncurry Lambda <$> bindingReorder (pattern,body)
53 Binop op leftExpr rightExpr ->
55 Binop op <$> reorder leftExpr <*> reorder rightExpr
58 Case <$> reorder expr <*> mapM bindingReorder cases
62 Data name <$> mapM reorder exprs
64 -- Just pipe the reorder though
68 Range lowExpr highExpr ->
69 Range <$> reorder lowExpr <*> reorder highExpr
72 ExplicitList <$> mapM reorder es
75 App <$> reorder func <*> reorder arg
77 MultiIf branches finally ->
79 <$> mapM (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
82 Access record field ->
87 Remove record field ->
92 Insert record field expr ->
98 Modify record fields ->
101 <*> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
105 <$> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
116 Out name expr tipe ->
117 (\e -> Out name e tipe) <$> reorder expr
119 Task name expr tipe ->
120 (\e -> Task name e tipe) <$> reorder expr
125 -- Actually do some reordering
127 do body' <- reorder body
129 -- Sort defs into strongly connected components.This
130 -- allows the programmer to write definitions in whatever
131 -- order they please, we can still define things in order
132 -- and generalize polymorphic functions when appropriate.
133 sccs <- Graph.stronglyConnComp <$> buildDefGraph defs
134 let defss = map Graph.flattenSCC sccs
136 -- remove let-bound variables from the context
137 forM_ defs $ \(Canonical.Definition pattern _ _) -> do
139 mapM free (ctors pattern)
142 foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
147ctors :: P.CanonicalPattern -> [String]
148ctors (A.A _ pattern) =
165 P.Data (V.Canonical home name) ps ->
167 V.Local -> name : rest
168 V.TopLevel _ -> name : rest
172 rest = concatMap ctors ps
175bound :: P.CanonicalPattern -> State (Set.Set String) ()
177 let boundVars = P.boundVarSet pattern
179 modify (\freeVars -> Set.difference freeVars boundVars)
183 :: (P.CanonicalPattern, Canonical.Expr)
184 -> State (Set.Set String) (P.CanonicalPattern, Canonical.Expr)
185bindingReorder (pattern, expr) =
186 do expr' <- reorder expr
188 mapM_ free (ctors pattern)
189 return (pattern, expr')
192-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
194-- This also reorders the all of the sub-expressions in the Def list.
197 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
199 do pdefsDeps <- mapM reorderAndGetDependencies defs
200 return $ realDeps (addKey pdefsDeps)
202 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
204 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
206 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
207 variableToKey (Canonical.Definition pattern _ _, key, _) =
208 [ (var, key) | var <- P.boundVarList pattern ]
210 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
211 variableToKeyMap pdefsDeps =
212 Map.fromList (concatMap variableToKey pdefsDeps)
214 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
216 map convert pdefsDeps
218 varDict = variableToKeyMap pdefsDeps
219 convert (pdef, key, deps) =
220 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
223reorderAndGetDependencies
225 -> State (Set.Set String) (Canonical.Def, [String])
226reorderAndGetDependencies (Canonical.Definition pattern expr mType) =
227 do globalFrees <- get
228 -- work in a fresh environment
230 expr' <- reorder expr
232 -- merge with global frees
233 modify (Set.union globalFrees)
234 return (Canonical.Definition 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