Source file identifiable.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
module type Thing = sig
type t
include Hashtbl.HashedType with type t := t
include Map.OrderedType with type t := t
val output : out_channel -> t -> unit
val print : Format.formatter -> t -> unit
end
module type Set = sig
module T : Set.OrderedType
include Set.S
with type elt = T.t
and type t = Set.Make (T).t
val output : out_channel -> t -> unit
val print : Format.formatter -> t -> unit
val to_string : t -> string
val of_list : elt list -> t
val map : (elt -> elt) -> t -> t
end
module type Map = sig
module T : Map.OrderedType
include Map.S
with type key = T.t
and type 'a t = 'a Map.Make (T).t
val of_list : (key * 'a) list -> 'a t
type 'a duplicate =
| Duplicate of { key : key; value1 : 'a; value2 : 'a }
val of_list_checked : (key * 'a) list -> ('a t, 'a duplicate) Result.t
val disjoint_union :
?eq:('a -> 'a -> bool) -> ?print:(Format.formatter -> 'a -> unit) -> 'a t ->
'a t -> 'a t
val union_right : 'a t -> 'a t -> 'a t
val union_left : 'a t -> 'a t -> 'a t
val union_merge : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
val rename : key t -> key -> key
val map_keys : (key -> key) -> 'a t -> 'a t
val keys : 'a t -> Set.Make(T).t
val data : 'a t -> 'a list
val of_set : (key -> 'a) -> Set.Make(T).t -> 'a t
val transpose_keys_and_data : key t -> key t
val transpose_keys_and_data_set : key t -> Set.Make(T).t t
val print :
(Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
end
module type Tbl = sig
module T : sig
type t
include Map.OrderedType with type t := t
include Hashtbl.HashedType with type t := t
end
include Hashtbl.S
with type key = T.t
and type 'a t = 'a Hashtbl.Make (T).t
val to_list : 'a t -> (T.t * 'a) list
val of_list : (T.t * 'a) list -> 'a t
val to_map : 'a t -> 'a Map.Make(T).t
val of_map : 'a Map.Make(T).t -> 'a t
val memoize : 'a t -> (key -> 'a) -> key -> 'a
val map : 'a t -> ('a -> 'b) -> 'b t
end
module Pair (A : Thing) (B : Thing) : Thing with type t = A.t * B.t = struct
type t = A.t * B.t
let compare (a1, b1) (a2, b2) =
let c = A.compare a1 a2 in
if c <> 0 then c
else B.compare b1 b2
let output oc (a, b) = Printf.fprintf oc " (%a, %a)" A.output a B.output b
let hash (a, b) = Hashtbl.hash (A.hash a, B.hash b)
let equal (a1, b1) (a2, b2) = A.equal a1 a2 && B.equal b1 b2
let print ppf (a, b) = Format.fprintf ppf " (%a, @ %a)" A.print a B.print b
end
module Make_map (T : Thing) = struct
include Map.Make (T)
let of_list l =
List.fold_left (fun map (id, v) -> add id v map) empty l
type 'a duplicate =
| Duplicate of { key : key; value1 : 'a; value2 : 'a }
let of_list_checked l =
let rec loop acc l =
match l with
| [] -> Ok acc
| (id, v) :: l ->
begin
match find_opt id acc with
| None ->
let acc = add id v acc in
loop acc l
| Some value1 ->
Error (Duplicate { key = id; value1; value2 = v })
end
in
loop empty l
let disjoint_union ?eq ?print m1 m2 =
union (fun id v1 v2 ->
let ok = match eq with
| None -> false
| Some eq -> eq v1 v2
in
if not ok then
let err =
match print with
| None ->
Format.asprintf "Map.disjoint_union %a" T.print id
| Some print ->
Format.asprintf "Map.disjoint_union %a => %a <> %a"
T.print id print v1 print v2
in
Misc.fatal_error err
else Some v1)
m1 m2
let union_right m1 m2 =
merge (fun _id x y -> match x, y with
| None, None -> None
| None, Some v
| Some v, None
| Some _, Some v -> Some v)
m1 m2
let union_left m1 m2 = union_right m2 m1
let union_merge f m1 m2 =
let aux _ m1 m2 =
match m1, m2 with
| None, m | m, None -> m
| Some m1, Some m2 -> Some (f m1 m2)
in
merge aux m1 m2
let rename m v =
try find v m
with Not_found -> v
let map_keys f m =
of_list (List.map (fun (k, v) -> f k, v) (bindings m))
let print f ppf s =
let elts ppf s = iter (fun id v ->
Format.fprintf ppf "@ (@[%a@ %a@])" T.print id f v) s in
Format.fprintf ppf "@[<1>{@[%a@ @]}@]" elts s
module T_set = Set.Make (T)
let keys map = fold (fun k _ set -> T_set.add k set) map T_set.empty
let data t = List.map snd (bindings t)
let of_set f set = T_set.fold (fun e map -> add e (f e) map) set empty
let transpose_keys_and_data map = fold (fun k v m -> add v k m) map empty
let transpose_keys_and_data_set map =
fold (fun k v m ->
let set =
match find v m with
| exception Not_found ->
T_set.singleton k
| set ->
T_set.add k set
in
add v set m)
map empty
end
module Make_set (T : Thing) = struct
include Set.Make (T)
let output oc s =
Printf.fprintf oc " ( ";
iter (fun v -> Printf.fprintf oc "%a " T.output v) s;
Printf.fprintf oc ")"
let print ppf s =
let elts ppf s = iter (fun e -> Format.fprintf ppf "@ %a" T.print e) s in
Format.fprintf ppf "@[<1>{@[%a@ @]}@]" elts s
let to_string s = Format.asprintf "%a" print s
let of_list l = match l with
| [] -> empty
| [t] -> singleton t
| t :: q -> List.fold_left (fun acc e -> add e acc) (singleton t) q
let map f s = of_list (List.map f (elements s))
end
module Make_tbl (T : Thing) = struct
include Hashtbl.Make (T)
module T_map = Make_map (T)
let to_list t =
fold (fun key datum elts -> (key, datum)::elts) t []
let of_list elts =
let t = create 42 in
List.iter (fun (key, datum) -> add t key datum) elts;
t
let to_map v = fold T_map.add v T_map.empty
let of_map m =
let t = create (T_map.cardinal m) in
T_map.iter (fun k v -> add t k v) m;
t
let memoize t f = fun key ->
try find t key with
| Not_found ->
let r = f key in
add t key r;
r
let map t f =
of_map (T_map.map f (to_map t))
end
module type S = sig
type t
module T : Thing with type t = t
include Thing with type t := T.t
module Set : Set with module T := T
module Map : Map with module T := T
module Tbl : Tbl with module T := T
end
module Make (T : Thing) = struct
module T = T
include T
module Set = Make_set (T)
module Map = Make_map (T)
module Tbl = Make_tbl (T)
end