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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
open Desc
open Tools
module Printer = struct
type 'a t = Format.formatter -> 'a -> unit
end
module Printers = Vector (Printer)
module PrinterSequence = Sequence (Printers.T)
type ('a, 'arity, 'b) typed_attribute_kind +=
| Attribute_printer : ('a, 'arity, 'a Printer.t) typed_attribute_kind
| Attribute_polyprinter :
('a, 'arity, 'arity PrinterSequence.t -> 'a Printer.t)
typed_attribute_kind
type 'kinds value =
| Value : {
desc :
('a, 'structure, 'arity, 'rec_group, 'kinds, 'positive, 'negative,
'direct, 'gadt) desc;
value : 'a;
printers : ('arity, 'direct) Printers.t;
} ->
'kinds value
let rec pp :
type a structure arity rec_group positive negative direct gadt .
(a, structure, arity, rec_group, 'kinds, positive, negative, direct, gadt)
desc ->
(arity, direct) Printers.t -> a Printer.t =
fun desc printers fmt x ->
let pp_tuple printers tuple =
let pp_tuple_item (Tuple.Fold { desc; value; _ })
comma =
if comma then
begin
Format.pp_print_string fmt ",";
Format.pp_print_space fmt ();
end;
Format.pp_open_box fmt 0;
pp desc printers fmt value;
Format.pp_close_box fmt ();
true in
Format.pp_open_box fmt 1;
Format.pp_print_string fmt "(";
ignore (Tuple.fold pp_tuple_item tuple false);
Format.pp_print_string fmt ")";
Format.pp_close_box fmt () in
let pp_record printers record =
let pp_record_field (Record.Fold { field; value; _ }) comma =
if comma then
begin
Format.pp_print_string fmt ";";
Format.pp_print_space fmt ();
end;
Format.pp_open_box fmt 0;
let pp_field label desc printers value =
Format.pp_print_string fmt label;
Format.pp_print_string fmt " =";
Format.pp_print_space fmt ();
pp desc printers fmt value in
begin match field with
| Poly { label; destruct; variables; _ } ->
let MakeAppend subarity = make_append variables.direct_count in
let printers =
printers |>
Printers.append None
variables.presences variables.direct_count variables.direct
variables.direct_count subarity in
let ForallDestruct { desc; destruct } =
destruct.forall_destruct variables.direct_count subarity in
pp_field label desc printers (destruct value)
| Mono { label; desc; _ } -> pp_field label desc printers value;
end;
Format.pp_close_box fmt ();
true in
Format.pp_open_box fmt 2;
Format.pp_print_string fmt "{ ";
ignore (Record.fold pp_record_field record false);
Format.pp_print_space fmt ();
Format.pp_print_string fmt "}";
Format.pp_close_box fmt () in
let rec to_list_aux :
type a structure arity rec_group positive negative direct gadt .
(a, structure, arity, rec_group, 'kinds, positive, negative, direct,
gadt) desc ->
a ->
(arity, direct) Printers.t ->
'kinds value list ->
'kinds value list option =
fun desc value printers acc ->
match desc with
| Constr { constructors; destruct; _ } ->
let Constructor.Destruct destruct =
Constructor.destruct constructors (destruct value) in
let printers =
match destruct.link with
| Constructor.Exists { exists_count; exists; variables; _ } ->
printers |>
Printers.append
(Some { item = fun fmt _ ->
Format.pp_print_string fmt "<poly>" })
variables.presences variables.direct_count variables.direct
exists_count exists
| Constructor.Constructor -> printers in
let open Tuple in
begin match destruct.name, destruct.kind, destruct.values with
| "[]", Constructor.Tuple { structure = []; _ }, _ ->
Some (List.rev acc)
| "::",
Constructor.Tuple { structure = [desc; tail_desc]; _ },
(value, (tail, ())) ->
to_list_aux tail_desc tail printers
(Value { desc; value; printers } :: acc)
| _ -> None
end
| Apply { arguments; desc; transfer } ->
let printers =
Printers.make { f = pp } arguments transfer printers in
to_list_aux desc value printers acc
| Rec { desc; _ } ->
to_list_aux desc value printers acc
| RecGroup { desc } ->
to_list_aux desc value printers acc
| SelectGADT { desc; _ } ->
to_list_aux desc value printers acc
| SubGADT { desc; _ } ->
to_list_aux desc value printers acc
| Name { desc; _ } ->
to_list_aux desc value printers acc
| _ ->
None in
let to_list desc value printers =
to_list_aux desc value printers [] in
match desc with
| Variable index ->
Printers.get index printers fmt x
| Builtin Bool -> Format.pp_print_bool fmt x
| Builtin Bytes ->
Format.pp_print_string fmt "\"";
Format.pp_print_string fmt (String.escaped (Bytes.to_string x));
Format.pp_print_string fmt "\""
| Builtin Char ->
Format.pp_print_string fmt "'";
Format.pp_print_string fmt (String.escaped (String.make 1 x));
Format.pp_print_string fmt "'"
| Builtin Float ->
Format.pp_print_float fmt x
| Builtin Int ->
Format.pp_print_int fmt x
| Builtin Int32 ->
Format.pp_print_string fmt (Int32.to_string x);
Format.pp_print_string fmt "l"
| Builtin Int64 ->
Format.pp_print_string fmt (Int64.to_string x);
Format.pp_print_string fmt "L"
| Builtin Nativeint ->
Format.pp_print_string fmt (Nativeint.to_string x);
Format.pp_print_string fmt "n"
| Builtin String ->
Format.pp_print_string fmt "\"";
Format.pp_print_string fmt (String.escaped x);
Format.pp_print_string fmt "\""
| Arrow _ ->
Format.pp_print_string fmt "<fun>"
| LabelledArrow _ ->
Format.pp_print_string fmt "<fun>"
| Array desc ->
Format.pp_open_box fmt 2;
Format.pp_print_string fmt "[|";
let pp_value comma value =
if comma then
begin
Format.pp_print_string fmt ";";
Format.pp_print_space fmt ();
end;
pp desc printers fmt value;
true in
ignore (Array.fold_left pp_value false x);
Format.pp_print_string fmt "|]";
Format.pp_close_box fmt ()
| Constr { constructors; destruct; _ } ->
let Constructor.Destruct destruct =
Constructor.destruct constructors (destruct x) in
let printers' =
match destruct.link with
| Constructor.Exists { exists_count; exists; variables; _ } ->
printers |>
Printers.append
(Some { item = fun fmt _ -> Format.pp_print_string fmt "<poly>" })
variables.presences variables.direct_count variables.direct
exists_count exists
| Constructor.Constructor -> printers in
let open Tuple in
begin match destruct.name, destruct.kind with
| "::", Constructor.Tuple { structure = [head_desc; tail_desc]; _ } ->
begin match to_list desc x printers with
| Some list ->
Format.pp_open_box fmt 1;
Format.pp_print_string fmt "[";
let pp_value comma (Value { desc; value; printers }) =
if comma then
begin
Format.pp_print_string fmt ";";
Format.pp_print_space fmt ();
end;
pp desc printers fmt value;
true in
ignore (List.fold_left pp_value false list);
Format.pp_print_string fmt "]";
Format.pp_close_box fmt ();
| None ->
let head, (tail, ()) = destruct.values in
Format.pp_open_box fmt 0;
pp head_desc printers' fmt head;
Format.pp_print_string fmt " ::";
Format.pp_print_space fmt ();
pp tail_desc printers' fmt tail;
Format.pp_close_box fmt ();
end
| _ ->
Format.pp_open_box fmt 0;
Format.pp_print_string fmt destruct.name;
begin match destruct.kind with
| Constructor.Tuple { structure = []; _ } -> ()
| Constructor.Tuple tuple ->
Format.pp_print_space fmt ();
pp_tuple printers' tuple
| Constructor.Record record ->
Format.pp_print_space fmt ();
pp_record printers' record
end;
Format.pp_close_box fmt ();
end
| Variant { constructors; destruct; _ } ->
let Variant.Destruct destruct =
Variant.destruct constructors (destruct x) in
begin match destruct.kind with
| Variant.Constructor { name; argument } ->
Format.pp_open_box fmt 0;
Format.pp_print_string fmt "`";
Format.pp_print_string fmt name;
begin match argument with
| Variant.None -> ()
| Variant.Some { desc; value } ->
Format.pp_print_space fmt ();
Format.pp_print_string fmt "(";
pp desc printers fmt value;
Format.pp_print_string fmt ")";
end;
Format.pp_close_box fmt ()
| Variant.Inherit { desc; value } ->
pp desc printers fmt value
end
| Object _ ->
Format.pp_print_string fmt "<obj>"
| Tuple { structure; destruct; _ } ->
pp_tuple printers
{ structure = Tuple.of_desc structure; values = destruct x }
| Record { structure; destruct; _ } ->
pp_record printers { structure; values = destruct x }
| Lazy desc ->
if Lazy.is_val x then
begin
Format.pp_open_box fmt 1;
Format.pp_print_string fmt "lazy (";
pp desc printers fmt (Lazy.force x);
Format.pp_print_string fmt ")";
Format.pp_close_box fmt ()
end
else
Format.pp_print_string fmt "<lazy>"
| Apply { arguments; desc; transfer } ->
let printers =
Printers.make { f = pp } arguments transfer printers in
pp desc printers fmt x
| Rec { desc; _ } ->
pp desc printers fmt x
| RecGroup { desc } ->
pp desc printers fmt x
| MapOpaque _ ->
Format.pp_print_string fmt "<opaque>"
| Opaque _ ->
Format.pp_print_string fmt "<opaque>"
| SelectGADT { desc; _ } ->
pp desc printers fmt x
| SubGADT { desc; _ } ->
pp desc printers fmt x
| Attributes { attributes; desc } ->
begin match attributes.typed Attribute_printer with
| Some printer ->
printer fmt x
| None ->
match attributes.typed Attribute_polyprinter with
| Some printer ->
let printers =
Printers.to_sequence (Some ({ item = fun _ _ -> assert false }))
printers in
printer printers fmt x
| None ->
pp desc printers fmt x
end
| Name { desc; _ } ->
pp desc printers fmt x
| _ -> .
let show desc printers x =
Format.asprintf "%a" (pp desc printers) x