1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Sort (definitions) where
4import Control.Monad.State
5import qualified Data.Graph as Graph
6import qualified Data.Map as Map
7import qualified Data.Maybe as Maybe
8import qualified Data.Set as Set
10import AST.Expression.General (Expr'(..))
11import qualified AST.Expression.Canonical as Canonical
12import qualified AST.Pattern as P
13import qualified AST.Variable as V
14import qualified Reporting.Annotation as A
21definitions :: Canonical.Expr -> Canonical.Expr
22definitions expression =
23 evalState (reorder expression) Set.empty
26free :: String -> State (Set.Set String) ()
31freeIfLocal :: V.Canonical -> State (Set.Set String) ()
32freeIfLocal (V.Canonical home name) =
35 V.TopLevel _ -> free name
36 V.BuiltIn -> return ()
37 V.Module _ -> return ()
44reorder :: Canonical.Expr -> State (Set.Set String) Canonical.Expr
45reorder (A.A ann expression) =
48 -- Be careful adding and restricting freeVars
53 Lambda pattern body ->
54 uncurry Lambda <$> bindingReorder (pattern,body)
56 Binop op leftExpr rightExpr ->
58 Binop op <$> reorder leftExpr <*> reorder rightExpr
61 Case <$> reorder expr <*> mapM bindingReorder cases
65 Data name <$> mapM reorder exprs
67 -- Just pipe the reorder though
71 Range lowExpr highExpr ->
72 Range <$> reorder lowExpr <*> reorder highExpr
75 ExplicitList <$> mapM reorder es
78 App <$> reorder func <*> reorder arg
80 If branches finally ->
82 <$> mapM (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
85 Access record field ->
90 Update record fields ->
93 <*> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
97 <$> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
112 error "DANGER - Program AST nodes should not be in def sorting."
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 <$> buildDefGraph defs
129 let defss = map Graph.flattenSCC sccs
131 -- remove let-bound variables from the context
132 forM_ defs $ \(Canonical.Def _ pattern _ _) -> do
134 mapM free (ctors pattern)
137 foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
142ctors :: P.Canonical -> [String]
143ctors (A.A _ pattern) =
160 P.Data (V.Canonical home name) ps ->
162 V.Local -> name : rest
163 V.TopLevel _ -> name : rest
167 rest = concatMap ctors ps
170bound :: P.Canonical -> State (Set.Set String) ()
174 P.boundVarSet pattern
176 modify (\freeVars -> Set.difference freeVars boundVars)
180 :: (P.Canonical, Canonical.Expr)
181 -> State (Set.Set String) (P.Canonical, Canonical.Expr)
182bindingReorder (pattern, expr) =
183 do expr' <- reorder expr
185 mapM_ free (ctors pattern)
186 return (pattern, expr')
190-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
193-- This also reorders the all of the sub-expressions in the Def list.
196 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
198 do pdefsDeps <- mapM reorderAndGetDependencies defs
199 return $ realDeps (addKey pdefsDeps)
201 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
203 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
205 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
206 variableToKey (Canonical.Def _ pattern _ _, key, _) =
207 [ (var, key) | var <- P.boundVarList pattern ]
209 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
210 variableToKeyMap pdefsDeps =
211 Map.fromList (concatMap variableToKey pdefsDeps)
213 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
215 map convert pdefsDeps
218 variableToKeyMap pdefsDeps
220 convert (pdef, key, deps) =
221 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
224reorderAndGetDependencies
226 -> State (Set.Set String) (Canonical.Def, [String])
227reorderAndGetDependencies (Canonical.Def facts pattern expr mType) =
228 do globalFrees <- get
229 -- work in a fresh environment
231 expr' <- reorder expr
233 -- merge with global frees
234 modify (Set.union globalFrees)
235 return (Canonical.Def 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