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
111 -- Actually do some reordering
113 do body' <- reorder body
115 -- Sort defs into strongly connected components.This
116 -- allows the programmer to write definitions in whatever
117 -- order they please, we can still define things in order
118 -- and generalize polymorphic functions when appropriate.
119 sccs <- Graph.stronglyConnComp <$> buildDefGraph defs
120 let defss = map Graph.flattenSCC sccs
122 -- remove let-bound variables from the context
123 forM_ defs $ \(Canonical.Definition _ pattern _ _) -> do
125 mapM free (ctors pattern)
128 foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
133ctors :: P.CanonicalPattern -> [String]
134ctors (A.A _ pattern) =
151 P.Data (V.Canonical home name) ps ->
153 V.Local -> name : rest
154 V.TopLevel _ -> name : rest
158 rest = concatMap ctors ps
161bound :: P.CanonicalPattern -> State (Set.Set String) ()
163 let boundVars = P.boundVarSet pattern
165 modify (\freeVars -> Set.difference freeVars boundVars)
169 :: (P.CanonicalPattern, Canonical.Expr)
170 -> State (Set.Set String) (P.CanonicalPattern, Canonical.Expr)
171bindingReorder (pattern, expr) =
172 do expr' <- reorder expr
174 mapM_ free (ctors pattern)
175 return (pattern, expr')
178-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
180-- This also reorders the all of the sub-expressions in the Def list.
183 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
185 do pdefsDeps <- mapM reorderAndGetDependencies defs
186 return $ realDeps (addKey pdefsDeps)
188 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
190 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
192 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
193 variableToKey (Canonical.Definition _ pattern _ _, key, _) =
194 [ (var, key) | var <- P.boundVarList pattern ]
196 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
197 variableToKeyMap pdefsDeps =
198 Map.fromList (concatMap variableToKey pdefsDeps)
200 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
202 map convert pdefsDeps
204 varDict = variableToKeyMap pdefsDeps
205 convert (pdef, key, deps) =
206 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
209reorderAndGetDependencies
211 -> State (Set.Set String) (Canonical.Def, [String])
212reorderAndGetDependencies (Canonical.Definition facts pattern expr mType) =
213 do globalFrees <- get
214 -- work in a fresh environment
216 expr' <- reorder expr
218 -- merge with global frees
219 modify (Set.union globalFrees)
220 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