comparison src/untangle.sml @ 131:5df655503288

Untangle
author Adam Chlipala <adamc@hcoop.net>
date Thu, 17 Jul 2008 12:19:44 -0400
parents
children 25b28625d4df
comparison
equal deleted inserted replaced
130:96bd3350e77d 131:5df655503288
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 Untangle :> UNTANGLE = struct
29
30 open Mono
31
32 structure U = MonoUtil
33 structure E = MonoEnv
34
35 structure IS = IntBinarySet
36 structure IM = IntBinaryMap
37
38 fun typ (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 {typ = typ,
58 exp = exp} IS.empty e
59 in
60 IM.insert (used, n, IS.intersection (usedHere, thisGroup))
61 end)
62 IM.empty vis
63
64 fun p_graph reachable =
65 IM.appi (fn (n, reachableHere) =>
66 (print (Int.toString n);
67 print ":";
68 IS.app (fn n' => (print " ";
69 print (Int.toString n'))) reachableHere;
70 print "\n")) reachable
71
72 (*val () = print "used:\n"
73 val () = p_graph used*)
74
75 fun expand reachable =
76 let
77 val changed = ref false
78
79 val reachable =
80 IM.mapi (fn (n, reachableHere) =>
81 IS.foldl (fn (n', reachableHere) =>
82 let
83 val more = valOf (IM.find (reachable, n'))
84 in
85 if IS.isEmpty (IS.difference (more, reachableHere)) then
86 reachableHere
87 else
88 (changed := true;
89 IS.union (more, reachableHere))
90 end)
91 reachableHere reachableHere) reachable
92 in
93 (reachable, !changed)
94 end
95
96 fun iterate reachable =
97 let
98 val (reachable, changed) = expand reachable
99 in
100 if changed then
101 iterate reachable
102 else
103 reachable
104 end
105
106 val reachable = iterate used
107
108 (*val () = print "reachable:\n"
109 val () = p_graph reachable*)
110
111 fun sccs (nodes, acc) =
112 case IS.find (fn _ => true) nodes of
113 NONE => acc
114 | SOME rep =>
115 let
116 val reachableHere = valOf (IM.find (reachable, rep))
117
118 val (nodes, scc) = IS.foldl (fn (node, (nodes, scc)) =>
119 if node = rep then
120 (nodes, scc)
121 else
122 let
123 val reachableThere =
124 valOf (IM.find (reachable, node))
125 in
126 if IS.member (reachableThere, rep) then
127 (IS.delete (nodes, node),
128 IS.add (scc, node))
129 else
130 (nodes, scc)
131 end)
132 (IS.delete (nodes, rep), IS.singleton rep) reachableHere
133 in
134 sccs (nodes, scc :: acc)
135 end
136
137 val sccs = rev (sccs (thisGroup, []))
138 (*val () = app (fn nodes => (print "SCC:";
139 IS.app (fn i => (print " ";
140 print (Int.toString i))) nodes;
141 print "\n")) sccs*)
142
143 val sccs = ListMergeSort.sort (fn (nodes1, nodes2) =>
144 let
145 val node1 = valOf (IS.find (fn _ => true) nodes1)
146 val node2 = valOf (IS.find (fn _ => true) nodes2)
147 val reachable1 = valOf (IM.find (reachable, node1))
148 in
149 IS.member (reachable1, node2)
150 end) sccs
151 (*val () = app (fn nodes => (print "SCC':";
152 IS.app (fn i => (print " ";
153 print (Int.toString i))) nodes;
154 print "\n")) sccs*)
155
156 fun isNonrec nodes =
157 case IS.find (fn _ => true) nodes of
158 NONE => NONE
159 | SOME node =>
160 let
161 val nodes = IS.delete (nodes, node)
162 val reachableHere = valOf (IM.find (reachable, node))
163 in
164 if IS.isEmpty nodes then
165 if IS.member (reachableHere, node) then
166 NONE
167 else
168 SOME node
169 else
170 NONE
171 end
172
173 val ds = map (fn nodes =>
174 case isNonrec nodes of
175 SOME node =>
176 let
177 val vi = valOf (List.find (fn (_, n, _, _, _) => n = node) vis)
178 in
179 (DVal vi, loc)
180 end
181 | NONE =>
182 (DValRec (List.filter (fn (_, n, _, _, _) => IS.member (nodes, n)) vis), loc))
183 sccs
184 in
185 ds
186 end
187 | _ => [dAll]
188 in
189 ListUtil.mapConcat decl file
190 end
191
192 end