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
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
109 error "DANGER - Program AST nodes should not be in def sorting."
117 -- Actually do some reordering
119 do body' <- reorder body
121 -- Sort defs into strongly connected components.This
122 -- allows the programmer to write definitions in whatever
123 -- order they please, we can still define things in order
124 -- and generalize polymorphic functions when appropriate.
125 sccs <- Graph.stronglyConnComp <$> buildDefGraph defs
126 let defss = map Graph.flattenSCC sccs
128 -- remove let-bound variables from the context
129 forM_ defs $ \(Canonical.Def _ pattern _ _) -> do
131 mapM free (ctors pattern)
134 foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
139ctors :: P.Canonical -> [String]
140ctors (A.A _ pattern) =
157 P.Data (V.Canonical home name) ps ->
159 V.Local -> name : rest
160 V.TopLevel _ -> name : rest
164 rest = concatMap ctors ps
167bound :: P.Canonical -> State (Set.Set String) ()
171 P.boundVarSet pattern
173 modify (\freeVars -> Set.difference freeVars boundVars)
177 :: (P.Canonical, Canonical.Expr)
178 -> State (Set.Set String) (P.Canonical, Canonical.Expr)
179bindingReorder (pattern, expr) =
180 do expr' <- reorder expr
182 mapM_ free (ctors pattern)
183 return (pattern, expr')
187-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
190-- This also reorders the all of the sub-expressions in the Def list.
193 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
195 do pdefsDeps <- mapM reorderAndGetDependencies defs
196 return $ realDeps (addKey pdefsDeps)
198 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
200 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
202 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
203 variableToKey (Canonical.Def _ pattern _ _, key, _) =
204 [ (var, key) | var <- P.boundVarList pattern ]
206 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
207 variableToKeyMap pdefsDeps =
208 Map.fromList (concatMap variableToKey pdefsDeps)
210 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
212 map convert pdefsDeps
215 variableToKeyMap pdefsDeps
217 convert (pdef, key, deps) =
218 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
221reorderAndGetDependencies
223 -> State (Set.Set String) (Canonical.Def, [String])
224reorderAndGetDependencies (Canonical.Def facts pattern expr mType) =
225 do globalFrees <- get
226 -- work in a fresh environment
228 expr' <- reorder expr
230 -- merge with global frees
231 modify (Set.union globalFrees)
232 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