@@ -1,11 +1,15 @@
2−module Transform.SortDefinitions (boundVars) where
2+module Transform.SortDefinitions (sortDefs) where
4import Control.Monad.State
4import Control.Monad.State
5+import Control.Applicative ((<$>))
5import qualified Data.Set as Set
6import qualified Data.Set as Set
6import qualified Data.Map as Map
7import qualified Data.Map as Map
8+import qualified SourceSyntax.Type as ST
7import SourceSyntax.Everything
9import SourceSyntax.Everything
8−
10+import qualified Data.Graph as Graph
11+import qualified Data.Map as Map
12+import qualified Data.Maybe as Maybe
10boundVars :: Pattern -> Set.Set String
14boundVars :: Pattern -> Set.Set String
11boundVars pattern =
15boundVars pattern =
@@ -17,38 +21,19 @@ boundVars pattern =
17 PAnything -> Set.empty
21 PAnything -> Set.empty
18 PLiteral _ -> Set.empty
22 PLiteral _ -> Set.empty
24+free :: String -> State (Set.Set String) ()
20free x = modify (Set.insert x)
25free x = modify (Set.insert x)
27+bound :: Set.Set String -> State (Set.Set String) ()
21bound boundVars = modify (\freeVars -> Set.difference freeVars boundVars)
28bound boundVars = modify (\freeVars -> Set.difference freeVars boundVars)
23−reorderAndGetDependencies pattern expr =
30+sortDefs :: LExpr t v -> LExpr t v
24− do globalFrees <- get
25− expr' <- reorder expr
31+sortDefs expr = evalState (reorder expr) Set.empty
27− modify (Set.union globalFrees)
28− let addDep var deps = Map.insert var localFrees deps
29− dependencies = Set.foldr addDep Map.empty (boundVars pattern)
30− return (expr', dependencies)
32reorder :: LExpr t v -> State (Set.Set String) (LExpr t v)
33reorder :: LExpr t v -> State (Set.Set String) (LExpr t v)
33reorder lexpr@(L a b expr) =
34reorder lexpr@(L a b expr) =
34 L a b `liftM`
35 L a b `liftM`
35 case expr of
36 case expr of
37− -- Actually do some reordering
39− do -- swap in a fresh environment
41− -- swap in the old environment
42− body' <- reorder body
43− bound (boundVars (patterns defs))
44− Let `liftM` defs' `ap` body'
47− patterns = flip concatMap defs $
49− Def pattern _ -> [pattern]
50− TypeAnnotation _ _ -> []
52 -- Be careful adding and restricting freeVars
37 -- Be careful adding and restricting freeVars
53 Var x -> free x >> return expr
38 Var x -> free x >> return expr
@@ -98,6 +83,35 @@ reorder lexpr@(L a b expr) =
99 Markdown _ -> return expr
84 Markdown _ -> return expr
86+ -- Actually do some reordering
88+ do body' <- reorder body
90+ -- Sort defs into strongly connected components.This
91+ -- allows the programmer to write definitions in whatever
92+ -- order they please, we can still define things in order
93+ -- and generalize polymorphic functions when appropriate.
94+ sccs <- Graph.stronglyConnComp <$> buildDefDict defs
95+ let defss = map Graph.flattenSCC sccs
97+ -- remove let-bound variables from the context
98+ let getPatterns def =
100+ Def pattern _ -> pattern
101+ TypeAnnotation name _ -> PVar name
102+ mapM (bound . boundVars . getPatterns) defs
104+ let addDefs ds bod = L a b (Let (concatMap toDefs ds) bod)
106+ toDefs (pattern, expr, Nothing) = [ Def pattern expr ]
107+ toDefs (PVar name, expr, Just tipe) =
108+ [ TypeAnnotation name tipe, Def (PVar name) expr ]
110+ L _ _ let' = foldr addDefs body' defss
101reorderField (label, expr) =
115reorderField (label, expr) =
102 (,) label `liftM` reorder expr
116 (,) label `liftM` reorder expr
@@ -110,3 +124,56 @@ bindingReorder (pattern,expr) =
110 bound (boundVars pattern)
124 bound (boundVars pattern)
111 return (pattern, expr')
125 return (pattern, expr')
128+type PDef t v = (Pattern, LExpr t v, Maybe ST.Type)
130+reorderAndGetDependencies :: PDef t v -> State (Set.Set String) (PDef t v, [String])
131+reorderAndGetDependencies (pattern, expr, mType) =
132+ do globalFrees <- get
133+ -- work in a fresh environment
135+ expr' <- reorder expr
137+ -- merge with global frees
138+ modify (Set.union globalFrees)
139+ return ((pattern, expr', mType), Set.toList localFrees)
142+-- This also reorders the all of the sub-expressions in the Def list.
143+buildDefDict :: [Def t v] -> State (Set.Set String) [(PDef t v, Int, [Int])]
145+ do pdefsDeps <- mapM reorderAndGetDependencies (getPDefs defs)
146+ return $ realDeps (addKey pdefsDeps)
149+ getPDefs :: [Def t v] -> [PDef t v]
150+ getPDefs defs = map (\(p,(e,t)) -> (p,e,t)) $
151+ Map.toList $ go defs Map.empty Map.empty
154+ Map.unions [ Map.difference ds ts
155+ , Map.intersectionWith (\(e,_) t -> (e,Just t)) ds ts ]
157+ go (def:defs) ds ts =
159+ Def p e -> go defs (Map.insert p (e, Nothing) ds) ts
160+ TypeAnnotation name tipe -> go defs ds (Map.insert (PVar name) tipe ts)
162+ addKey :: [(PDef t v, [String])] -> [(PDef t v, Int, [String])]
163+ addKey = zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
165+ variableToKey :: (PDef t v, Int, [String]) -> [(String, Int)]
166+ variableToKey ((pattern, _, _), key, _) =
167+ [ (var, key) | var <- Set.toList (boundVars pattern) ]
169+ variableToKeyMap :: [(PDef t v, Int, [String])] -> Map.Map String Int
170+ variableToKeyMap pdefsDeps =
171+ Map.fromList (concatMap variableToKey pdefsDeps)
173+ realDeps :: [(PDef t v, Int, [String])] -> [(PDef t v, Int, [Int])]
174+ realDeps pdefsDeps = map convert pdefsDeps
176+ varDict = variableToKeyMap pdefsDeps
177+ convert (pdef, key, deps) =
178+ (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)