comparison src/core_untangle.sml @ 454:9163f8014f9b

Nested save compiles
author Adam Chlipala <adamc@hcoop.net>
date Sat, 01 Nov 2008 21:24:43 -0400
parents
children d4a81273d4b1
comparison
equal deleted inserted replaced
453:787d4931fb07 454:9163f8014f9b
1 (* Copyright (c) 2008, Adam Chlipala
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - The names of contributors may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *)
27
28 structure CoreUntangle :> CORE_UNTANGLE = struct
29
30 open Core
31
32 structure U = CoreUtil
33 structure E = CoreEnv
34
35 structure IS = IntBinarySet
36 structure IM = IntBinaryMap
37
38 fun default (k, s) = s
39
40 fun exp (e, s) =
41 case e of
42 ENamed n => IS.add (s, n)
43
44 | _ => s
45
46 fun untangle file =
47 let
48 fun decl (dAll as (d, loc)) =
49 case d of
50 DValRec vis =>
51 let
52 val thisGroup = foldl (fn ((_, n, _, _, _), thisGroup) =>
53 IS.add (thisGroup, n)) IS.empty vis
54
55 val used = foldl (fn ((_, n, _, e, _), used) =>
56 let
57 val usedHere = U.Exp.fold {con = default,
58 kind = default,
59 exp = exp} IS.empty e
60 in
61 IM.insert (used, n, IS.intersection (usedHere, thisGroup))
62 end)
63 IM.empty vis
64
65 fun p_graph reachable =
66 IM.appi (fn (n, reachableHere) =>
67 (print (Int.toString n);
68 print ":";
69 IS.app (fn n' => (print " ";
70 print (Int.toString n'))) reachableHere;
71 print "\n")) reachable
72
73 (*val () = print "used:\n"
74 val () = p_graph used*)
75
76 fun expand reachable =
77 let
78 val changed = ref false
79
80 val reachable =
81 IM.mapi (fn (n, reachableHere) =>
82 IS.foldl (fn (n', reachableHere) =>
83 let
84 val more = valOf (IM.find (reachable, n'))
85 in
86 if IS.isEmpty (IS.difference (more, reachableHere)) then
87 reachableHere
88 else
89 (changed := true;
90 IS.union (more, reachableHere))
91 end)
92 reachableHere reachableHere) reachable
93 in
94 (reachable, !changed)
95 end
96
97 fun iterate reachable =
98 let
99 val (reachable, changed) = expand reachable
100 in
101 if changed then
102 iterate reachable
103 else
104 reachable
105 end
106
107 val reachable = iterate used
108
109 (*val () = print "reachable:\n"
110 val () = p_graph reachable*)
111
112 fun sccs (nodes, acc) =
113 case IS.find (fn _ => true) nodes of
114 NONE => acc
115 | SOME rep =>
116 let
117 val reachableHere = valOf (IM.find (reachable, rep))
118
119 val (nodes, scc) = IS.foldl (fn (node, (nodes, scc)) =>
120 if node = rep then
121 (nodes, scc)
122 else
123 let
124 val reachableThere =
125 valOf (IM.find (reachable, node))
126 in
127 if IS.member (reachableThere, rep) then
128 (IS.delete (nodes, node),
129 IS.add (scc, node))
130 else
131 (nodes, scc)
132 end)
133 (IS.delete (nodes, rep), IS.singleton rep) reachableHere
134 in
135 sccs (nodes, scc :: acc)
136 end
137
138 val sccs = sccs (thisGroup, [])
139 (*val () = app (fn nodes => (print "SCC:";
140 IS.app (fn i => (print " ";
141 print (Int.toString i))) nodes;
142 print "\n")) sccs*)
143
144 fun depends nodes1 nodes2 =
145 let
146 val node1 = valOf (IS.find (fn _ => true) nodes1)
147 val node2 = valOf (IS.find (fn _ => true) nodes2)
148 val reachable1 = valOf (IM.find (reachable, node1))
149 in
150 IS.member (reachable1, node2)
151 end
152
153 fun findReady (sccs, passed) =
154 case sccs of
155 [] => raise Fail "Untangle: Unable to topologically sort 'val rec'"
156 | nodes :: sccs =>
157 if List.exists (depends nodes) passed
158 orelse List.exists (depends nodes) sccs then
159 findReady (sccs, nodes :: passed)
160 else
161 (nodes, List.revAppend (passed, sccs))
162
163 fun topo (sccs, acc) =
164 case sccs of
165 [] => rev acc
166 | _ =>
167 let
168 val (node, sccs) = findReady (sccs, [])
169 in
170 topo (sccs, node :: acc)
171 end
172
173 val sccs = topo (sccs, [])
174 (*val () = app (fn nodes => (print "SCC':";
175 IS.app (fn i => (print " ";
176 print (Int.toString i))) nodes;
177 print "\n")) sccs*)
178
179 fun isNonrec nodes =
180 case IS.find (fn _ => true) nodes of
181 NONE => NONE
182 | SOME node =>
183 let
184 val nodes = IS.delete (nodes, node)
185 val reachableHere = valOf (IM.find (reachable, node))
186 in
187 if IS.isEmpty nodes then
188 if IS.member (reachableHere, node) then
189 NONE
190 else
191 SOME node
192 else
193 NONE
194 end
195
196 val ds = map (fn nodes =>
197 case isNonrec nodes of
198 SOME node =>
199 let
200 val vi = valOf (List.find (fn (_, n, _, _, _) => n = node) vis)
201 in
202 (DVal vi, loc)
203 end
204 | NONE =>
205 (DValRec (List.filter (fn (_, n, _, _, _) => IS.member (nodes, n)) vis), loc))
206 sccs
207 in
208 ds
209 end
210 | _ => [dAll]
211 in
212 ListUtil.mapConcat decl file
213 end
214
215 end