on 93d2efe help sign in
elk/compiler/Transform/SortDefinitions.hs
156 lines 5.0 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2module Transform.SortDefinitions (sortDefs) 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
10import SourceSyntax.Annotation
11import SourceSyntax.Expression
12import qualified SourceSyntax.Pattern as P
13import qualified SourceSyntax.Variable as V
15ctors :: P.Pattern -> [String]
16ctors pattern =
17 case pattern of
18 P.Var _ -> []
19 P.Alias _ p -> ctors p
20 P.Data ctor ps -> ctor : concatMap ctors ps
21 P.Record _ -> []
22 P.Anything -> []
23 P.Literal _ -> []
25free :: String -> State (Set.Set String) ()
26free x = modify (Set.insert x)
28bound :: Set.Set String -> State (Set.Set String) ()
29bound boundVars = modify (\freeVars -> Set.difference freeVars boundVars)
31sortDefs :: Expr -> Expr
32sortDefs expr = evalState (reorder expr) Set.empty
34reorder :: Expr -> State (Set.Set String) Expr
35reorder (A ann expr) =
36 A ann <$>
37 case expr of
38 -- Be careful adding and restricting freeVars
39 Var (V.Raw x) -> free x >> return expr
41 Lambda p e ->
42 uncurry Lambda <$> bindingReorder (p,e)
44 Binop op e1 e2 ->
45 do free op
46 Binop op <$> reorder e1 <*> reorder e2
48 Case e cases ->
49 Case <$> reorder e <*> mapM bindingReorder cases
51 Data name es ->
52 do free name
53 Data name <$> mapM reorder es
55 -- Just pipe the reorder though
56 Literal _ -> return expr
58 Range e1 e2 ->
59 Range <$> reorder e1 <*> reorder e2
61 ExplicitList es ->
62 ExplicitList <$> mapM reorder es
64 App e1 e2 ->
65 App <$> reorder e1 <*> reorder e2
67 MultiIf branches ->
68 MultiIf <$> mapM (\(e1,e2) -> (,) <$> reorder e1 <*> reorder e2) branches
70 Access e lbl ->
71 Access <$> reorder e <*> return lbl
73 Remove e lbl ->
74 Remove <$> reorder e <*> return lbl
76 Insert e lbl v ->
77 Insert <$> reorder e <*> return lbl <*> reorder v
79 Modify e fields ->
80 Modify <$> reorder e <*> mapM (\(k,v) -> (,) k <$> reorder v) fields
82 Record fields ->
83 Record <$> mapM (\(k,v) -> (,) k <$> reorder v) fields
85 Markdown uid md es -> Markdown uid md <$> mapM reorder es
87 GLShader _ _ _ -> return expr
89 PortOut name st signal -> PortOut name st <$> reorder signal
91 PortIn name st -> return $ PortIn name st
93 -- Actually do some reordering
94 Let defs body ->
95 do body' <- reorder body
97 -- Sort defs into strongly connected components.This
98 -- allows the programmer to write definitions in whatever
99 -- order they please, we can still define things in order
100 -- and generalize polymorphic functions when appropriate.
101 sccs <- Graph.stronglyConnComp <$> buildDefDict defs
102 let defss = map Graph.flattenSCC sccs
104 -- remove let-bound variables from the context
105 forM_ defs $ \(Definition pattern _ _) -> do
106 bound (P.boundVars pattern)
107 mapM free (ctors pattern)
109 let A _ let' = foldr (\ds bod -> A ann (Let ds bod)) body' defss
111 return let'
113bindingReorder :: (P.Pattern, Expr) -> State (Set.Set String) (P.Pattern, Expr)
114bindingReorder (pattern,expr) =
115 do expr' <- reorder expr
116 bound (P.boundVars pattern)
117 mapM_ free (ctors pattern)
118 return (pattern, expr')
121reorderAndGetDependencies :: Def -> State (Set.Set String) (Def, [String])
122reorderAndGetDependencies (Definition pattern expr mType) =
123 do globalFrees <- get
124 -- work in a fresh environment
125 put Set.empty
126 expr' <- reorder expr
127 localFrees <- get
128 -- merge with global frees
129 modify (Set.union globalFrees)
130 return (Definition pattern expr' mType, Set.toList localFrees)
133-- This also reorders the all of the sub-expressions in the Def list.
134buildDefDict :: [Def] -> State (Set.Set String) [(Def, Int, [Int])]
135buildDefDict defs =
136 do pdefsDeps <- mapM reorderAndGetDependencies defs
137 return $ realDeps (addKey pdefsDeps)
139 where
140 addKey :: [(Def, [String])] -> [(Def, Int, [String])]
141 addKey = zipWith (\n (pdef,deps) -> (pdef,n,deps)) [0..]
143 variableToKey :: (Def, Int, [String]) -> [(String, Int)]
144 variableToKey (Definition pattern _ _, key, _) =
145 [ (var, key) | var <- Set.toList (P.boundVars pattern) ]
147 variableToKeyMap :: [(Def, Int, [String])] -> Map.Map String Int
148 variableToKeyMap pdefsDeps =
149 Map.fromList (concatMap variableToKey pdefsDeps)
151 realDeps :: [(Def, Int, [String])] -> [(Def, Int, [Int])]
152 realDeps pdefsDeps = map convert pdefsDeps
153 where
154 varDict = variableToKeyMap pdefsDeps
155 convert (pdef, key, deps) =
156 (pdef, key, Maybe.mapMaybe (flip Map.lookup varDict) deps)