package refl

  1. Overview
  2. Docs

Source file show.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
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
OCaml

Innovation. Community. Security.