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 If branches finally ->
79 <$> mapM (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
82 Access record field ->
87 Update record fields ->
90 <*> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
94 <$> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
105 Out name expr tipe ->
106 (\e -> Out name e tipe) <$> reorder expr
108 Task name expr tipe ->
109 (\e -> Task name e tipe) <$> reorder expr
114 -- Actually do some reordering
116 do body' <- reorder body
118 -- Sort defs into strongly connected components.This
119 -- allows the programmer to write definitions in whatever
120 -- order they please, we can still define things in order
121 -- and generalize polymorphic functions when appropriate.
122 sccs <- Graph.stronglyConnComp <$> buildDefGraph defs
123 let defss = map Graph.flattenSCC sccs
125 -- remove let-bound variables from the context
126 forM_ defs $ \(Canonical.Definition _ pattern _ _) -> do
128 mapM free (ctors pattern)
131 foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
136ctors :: P.CanonicalPattern -> [String]
137ctors (A.A _ pattern) =
154 P.Data (V.Canonical home name) ps ->
156 V.Local -> name : rest
157 V.TopLevel _ -> name : rest
161 rest = concatMap ctors ps
164bound :: P.CanonicalPattern -> State (Set.Set String) ()
166 let boundVars = P.boundVarSet pattern
168 modify (\freeVars -> Set.difference freeVars boundVars)
172 :: (P.CanonicalPattern, Canonical.Expr)
173 -> State (Set.Set String) (P.CanonicalPattern, Canonical.Expr)
174bindingReorder (pattern, expr) =
175 do expr' <- reorder expr
177 mapM_ free (ctors pattern)
178 return (pattern, expr')
181-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
183-- This also reorders the all of the sub-expressions in the Def list.
186 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
188 do pdefsDeps <- mapM reorderAndGetDependencies defs
189 return $ realDeps (addKey pdefsDeps)
191 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
193 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
195 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
196 variableToKey (Canonical.Definition _ pattern _ _, key, _) =
197 [ (var, key) | var <- P.boundVarList pattern ]
199 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
200 variableToKeyMap pdefsDeps =
201 Map.fromList (concatMap variableToKey pdefsDeps)
203 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
205 map convert pdefsDeps
207 varDict = 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