1 (* Adapted from Pottier's PP compiler *)
3 (* A universe is a record, whose address defines the identity of the
4 universe. The integer counter [next] holds the number of the next
5 fresh atom. The [name] field holds the name of the universe. *)
12 let new_universe name = {
17 (* An atom is a pair of a universe and an integer. The latter defines
18 the atom's identity within its universe. *)
28 let equal (u1, id1) (u2, id2) =
30 ((id1 : int) = (id2 : int))
32 let compare (u1, id1) (u2, id2) =
34 compare (id1 : int) (id2 : int)
36 let flex_compare (u1, id1) (u2, id2) =
37 if String.compare u1.name u2.name = 0 then Pervasives.compare id1 id2
38 else String.compare u1.name u2.name
40 let flex_equal l1 l2 = flex_compare l1 l2 = 0
42 let universe_of (u, _) = u
44 let same_universe (u1, _) (u2, _) = u1 = u2
46 let ends_with_a_digit s =
47 let n = String.length s in
48 n > 0 && s.[n-1] >= '0' && s.[n-1] <= '9'
50 (* This function is injective, that is, [u] and [id] can be recovered
51 out of [print (u, id)]. *)
54 Printf.sprintf "%s%s%d" u.name (if ends_with_a_digit u.name then "_" else "") id
56 (* Added by Nicolas Ayache: more flexible maps and sets where atoms
57 from different universes can coexist. *)
61 module OrderedLabel = struct
63 let compare = flex_compare
66 module FlexSet = Set.Make (OrderedLabel)
68 module FlexMap = Map.Make (OrderedLabel)
71 module OrderedInt = struct
73 let compare x1 x2 = x1 - x2
76 (* We internally rely upon Objective Caml's integer sets and maps. *)
78 module ISet = Set.Make (OrderedInt)
79 module IMap = Map.Make (OrderedInt)
85 (* A set is either empty or a pair of a universe and a (possibly
86 empty) internal set. The fact that we do not require the empty
87 set to be explicitly associated with a universe means that
88 [empty] can be a constant, as opposed to an operation that
89 expects a universe as a parameter. *)
96 | U of universe * ISet.t
101 let is_empty = function
107 let mem (u1, x) = function
112 (u1 = u2) && (ISet.mem x s)
114 let add (u1, x) = function
116 U (u1, ISet.singleton x)
121 let remove (u1, x) = function
126 (* set can become empty but retains its universe *)
127 U (u1, ISet.remove x s)
133 add x1 (singleton x2)
136 List.fold_right add xs empty
143 | U (u1, s1), U (u2, s2) ->
145 U (u1, ISet.union s1 s2)
152 | U (u1, s1), U (u2, s2) ->
154 U (u1, ISet.inter s1 s2)
157 is_empty (inter s1 s2)
165 | U (u1, s1), U (u2, s2) ->
167 U (u1, ISet.diff s1 s2)
169 let iter f = function
173 ISet.iter (fun x -> f (u, x)) s
180 ISet.fold (fun x accu -> f (u, x) accu) s accu
182 let choose = function
193 | U (u1, s1), U (u2, s2) ->
197 let cardinal = function
203 let elements = function
207 List.map (fun x -> (u, x)) (ISet.elements s)
209 let filter p = function
213 U (u, ISet.filter (fun x -> p (u, x)) s)
217 let s = remove x s in
220 let rec exhaust s accu f =
225 let s', accu = f x accu in
226 exhaust (union s s') accu f
231 seplist comma (fun () x -> print x) () (elements s)
239 (* A map is either empty or a pair of a universe and a (possibly
240 empty) internal map. The fact that we do not require the empty
241 map to be explicitly associated with a universe means that
242 [empty] can be a constant, as opposed to an operation that
243 expects a universe as a parameter. *)
250 | U of universe * 'a IMap.t
255 let is_empty = function
261 let mem (u1, x) = function
268 let add (u1, x) d = function
270 U (u1, IMap.add x d IMap.empty)
273 U (u1, IMap.add x d m)
275 let remove (u1, x) = function
280 U (u1, IMap.remove x m)
285 let find (u1, x) = function
292 let iter f = function
296 IMap.iter (fun x d -> f (u, x) d) m
303 IMap.fold (fun x d accu -> f (u, x) d accu) m accu
311 let mapi f = function
315 U (u, IMap.mapi (fun x d -> f (u, x) d) m)
317 let domain = function
321 Set.U (u, IMap.fold (fun x _ s ->
326 let lift f = function
330 U (u, ISet.fold (fun x m ->
331 IMap.add x (f (u, x)) m
339 let label = fresh u in
358 (* An imperative interface to maps. *)
360 module ImperativeMap = struct
385 (* Maps of atoms to sets of atoms. *)
387 module SetMap = SetMap.MakeHomo(Set)(Map)