Import Upstream version 20180207
[hcoop/debian/mlton.git] / mlton / ssa / equatable.sml
CommitLineData
7f918cf1
CE
1(* Copyright (C) 2004-2006 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 *
4 * MLton is released under a BSD-style license.
5 * See the file MLton-LICENSE for details.
6 *)
7
8structure Equatable: EQUATABLE =
9struct
10
11structure Set = DisjointSet
12
13datatype 'a delay =
14 Computed of 'a
15 | Uncomputed of {compute: unit -> 'a,
16 whenComputed: ('a -> unit) AppendList.t ref}
17
18datatype 'a t = T of 'a delay Set.t
19
20fun layout (T s, f) =
21 case Set.! s of
22 Computed a => f a
23 | Uncomputed _ => Layout.str "<uncomputed>"
24
25fun delay f =
26 T (Set.singleton (Uncomputed {compute = f,
27 whenComputed = ref AppendList.empty}))
28
29fun new a = T (Set.singleton (Computed a))
30
31fun equals (T s, T s') = Set.equals (s, s')
32
33fun value (T s) =
34 case Set.! s of
35 Computed a => a
36 | Uncomputed {compute, whenComputed} =>
37 let
38 val a = compute ()
39 val () = Set.:= (s, Computed a)
40 val () = AppendList.foreach (!whenComputed, fn f => f a)
41 in
42 a
43 end
44
45fun equate (T s, T s', combine) =
46 if Set.equals (s, s')
47 then ()
48 else
49 let
50 val d = Set.! s
51 val d' = Set.! s'
52 val () = Set.union (s, s')
53 fun one (a, {compute = _, whenComputed}) =
54 (* Must set the value before calling the whenComputed, because
55 * those may look at the value (which would cause it to be set,
56 * which would then be overwritten).
57 *)
58 (Set.:= (s, Computed a)
59 ; AppendList.foreach (!whenComputed, fn f => f a))
60 in
61 case (d, d') of
62 (Computed a, Computed a') =>
63 Set.:= (s, Computed (combine (a, a')))
64 | (Computed a, Uncomputed u) => one (a, u)
65 | (Uncomputed u, Computed a) => one (a, u)
66 | (Uncomputed {compute, whenComputed = w},
67 Uncomputed {whenComputed = w', ...}) =>
68 Set.:=
69 (s, Uncomputed {compute = compute,
70 whenComputed = ref (AppendList.append (!w, !w'))})
71 end
72
73fun whenComputed (T s, f): unit =
74 case Set.! s of
75 Computed a => f a
76 | Uncomputed {whenComputed = w, ...} => AppendList.push (w, f)
77
78end