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
102 -- Actually do some reordering
104 do body' <- reorder body
106 -- Sort defs into strongly connected components.This
107 -- allows the programmer to write definitions in whatever
108 -- order they please, we can still define things in order
109 -- and generalize polymorphic functions when appropriate.
110 sccs <- Graph.stronglyConnComp <$> buildDefGraph defs
111 let defss = map Graph.flattenSCC sccs
113 -- remove let-bound variables from the context
114 forM_ defs $ \(Canonical.Definition _ pattern _ _) -> do
116 mapM free (ctors pattern)
119 foldr (\ds bod -> A.A ann (Let ds bod)) body' defss
124ctors :: P.Canonical -> [String]
125ctors (A.A _ pattern) =
142 P.Data (V.Canonical home name) ps ->
144 V.Local -> name : rest
145 V.TopLevel _ -> name : rest
149 rest = concatMap ctors ps
152bound :: P.Canonical -> State (Set.Set String) ()
156 P.boundVarSet pattern
158 modify (\freeVars -> Set.difference freeVars boundVars)
162 :: (P.Canonical, Canonical.Expr)
163 -> State (Set.Set String) (P.Canonical, Canonical.Expr)
164bindingReorder (pattern, expr) =
165 do expr' <- reorder expr
167 mapM_ free (ctors pattern)
168 return (pattern, expr')
172-- BUILD DEPENDENCY GRAPH BETWEEN DEFINITIONS
175-- This also reorders the all of the sub-expressions in the Def list.
178 -> State (Set.Set String) [(Canonical.Def, Int, [Int])]
180 do pdefsDeps <- mapM reorderAndGetDependencies defs
181 return $ realDeps (addKey pdefsDeps)
183 addKey :: [(Canonical.Def, [String])] -> [(Canonical.Def, Int, [String])]
185 zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
187 variableToKey :: (Canonical.Def, Int, [String]) -> [(String, Int)]
188 variableToKey (Canonical.Definition _ pattern _ _, key, _) =
189 [ (var, key) | var <- P.boundVarList pattern ]
191 variableToKeyMap :: [(Canonical.Def, Int, [String])] -> Map.Map String Int
192 variableToKeyMap pdefsDeps =
193 Map.fromList (concatMap variableToKey pdefsDeps)
195 realDeps :: [(Canonical.Def, Int, [String])] -> [(Canonical.Def, Int, [Int])]
197 map convert pdefsDeps
200 variableToKeyMap pdefsDeps
202 convert (pdef, key, deps) =
203 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)
206reorderAndGetDependencies
208 -> State (Set.Set String) (Canonical.Def, [String])
209reorderAndGetDependencies (Canonical.Definition facts pattern expr mType) =
210 do globalFrees <- get
211 -- work in a fresh environment
213 expr' <- reorder expr
215 -- merge with global frees
216 modify (Set.union globalFrees)
217 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