• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Kakadu / zanuda / 32

04 Oct 2025 02:22PM UTC coverage: 86.294% (+0.04%) from 86.255%
32

push

github

Kakadu
Disable matching of or-patterns (TODO: fix properly #76)

It was failing but it is not obvious how to write correctly.
Or-patterns are currently filtered out.
It's incorrect by I'm in a hurry

Signed-off-by: Kakadu <Kakadu@pm.me>

2210 of 2561 relevant lines covered (86.29%)

524.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.0
/src/pattern/Tast_pattern.ml
1
[@@@ocaml.text "/*"]
2

3
(** Copyright 2021-2025, Kakadu. *)
4

5
(** SPDX-License-Identifier: LGPL-3.0-or-later *)
6

7
[@@@ocaml.text "/*"]
8

9
module Ast_pattern0 = struct
10
  exception Expected of Location.t * string
11

12
  let fail loc expected = raise (Expected (loc, expected))
70,177✔
13

14
  type context =
15
    { (* [matched] counts how many constructors have been matched. This is used to find what
16
         pattern matches the most some piece of ast in [Ast_pattern.alt]. In the case where
17
         all branches fail to match, we report the error from the one that matches the
18
         most.
19
         This is only incremented by combinators that can fail. *)
20
      mutable matched : int
21
    }
22

23
  type ('matched_value, 'k, 'k_result) t =
24
    | T of (context -> Location.t -> 'matched_value -> 'k -> 'k_result)
25

26
  (* end of copy-paste from https://github.com/ocaml-ppx/ppxlib/blob/0.22.2/src/ast_pattern0.ml *)
27
  (* TODO: deal with licencing issues *)
28
end
29

30
open Location
31
open Format
32
open Ast_pattern0
33

34
let debug_enabled = false
35

36
let log fmt =
37
  let open Format in
1,203✔
38
  if debug_enabled then kasprintf (printf "%s\n%!") fmt else ifprintf std_formatter fmt
×
39
;;
40

41
type ('a, 'b, 'c) t = ('a, 'b, 'c) Ast_pattern0.t
42

43
let save_context ctx = ctx.matched
123,276✔
44
let restore_context ctx backup = ctx.matched <- backup
81,058✔
45
let incr_matched c = c.matched <- c.matched + 1
4,073✔
46

47
let parse (T f) loc ?on_error x k =
48
  try f { matched = 0 } loc x k with
1,605✔
49
  | Expected (loc, expected) ->
29,108✔
50
    (match on_error with
51
     | None -> Location.raise_errorf ~loc "%s expected" expected
×
52
     | Some f -> f expected)
29,108✔
53
;;
54

55
module Packed = struct
56
  type ('a, 'b) t = T : ('a, 'b, 'c) Ast_pattern0.t * 'b -> ('a, 'c) t
57

58
  let create t f = T (t, f)
×
59
  let parse (T (t, f)) loc x = parse t loc x f
×
60
end
61

62
let __ : 'a 'b. ('a, 'a -> 'b, 'b) t =
63
  T
64
    (fun ctx _loc x k ->
65
      incr_matched ctx;
2,800✔
66
      k x)
2,800✔
67
;;
68

69
let as__ : 'a 'b 'c. ('a, 'b, 'c) t -> ('a, 'a -> 'b, 'c) t =
70
  fun (T f1) ->
71
  T
3,610✔
72
    (fun ctx loc x k ->
73
      let k = f1 ctx loc x (k x) in
260✔
74
      k)
120✔
75
;;
76

77
let pair (T f1) (T f2) =
78
  T
9,400✔
79
    (fun ctx loc (x1, x2) k ->
80
      let k = f1 ctx loc x1 k in
410✔
81
      let k = f2 ctx loc x2 k in
391✔
82
      k)
262✔
83
;;
84

85
let ( ** ) = pair
86

87
let __' =
88
  T
89
    (fun ctx loc x k ->
90
      incr_matched ctx;
21✔
91
      k { loc; txt = x })
21✔
92
;;
93

94
let drop : 'a 'b. ('a, 'b, 'b) t =
95
  T
96
    (fun ctx _loc _ k ->
97
      incr_matched ctx;
1,201✔
98
      k)
1,201✔
99
;;
100

101
let cst ~to_string ?(equal = Stdlib.( = )) v =
5,407✔
102
  T
5,407✔
103
    (fun ctx loc x k ->
104
      if equal x v
135✔
105
      then (
51✔
106
        incr_matched ctx;
107
        (* printf "cst succeeded for %s\n%!" (to_string v); *)
108
        k)
51✔
109
      else fail loc (to_string v))
84✔
110
;;
111

112
let int v = cst ~to_string:Int.to_string v
470✔
113
let char v = cst ~to_string:(Printf.sprintf "%C") v
×
114
let string v = cst ~to_string:(Printf.sprintf "%S") v
4,937✔
115
let float v = cst ~to_string:Float.to_string v
×
116
let int32 v = cst ~to_string:Int32.to_string v
×
117
let int64 v = cst ~to_string:Int64.to_string v
×
118
let nativeint v = cst ~to_string:Nativeint.to_string v
×
119
let bool v = cst ~to_string:Bool.to_string v
×
120

121
let false_ =
122
  T
123
    (fun ctx loc x k ->
124
      match x with
×
125
      | false ->
×
126
        ctx.matched <- ctx.matched + 1;
127
        k
128
      | _ -> fail loc "false")
×
129
;;
130

131
let true_ =
132
  T
133
    (fun ctx loc x k ->
134
      match x with
×
135
      | true ->
×
136
        ctx.matched <- ctx.matched + 1;
137
        k
138
      | _ -> fail loc "true")
×
139
;;
140

141
let nil =
142
  T
143
    (fun ctx loc x k ->
144
      log "trying [] \n%!";
405✔
145
      match x with
405✔
146
      | [] ->
317✔
147
        ctx.matched <- ctx.matched + 1;
148
        k
149
      | _ -> fail loc "[]")
88✔
150
;;
151

152
let ( ^:: ) (T f0) (T f1) =
153
  T
22,529✔
154
    (fun ctx loc x k ->
155
      match x with
654✔
156
      | x0 :: x1 ->
603✔
157
        ctx.matched <- ctx.matched + 1;
158
        (* Format.printf "trying elem of cons cell\n%!"; *)
159
        let k = f0 ctx loc x0 k in
160
        (* Format.printf "trying tail of cons cell\n%!"; *)
161
        let k = f1 ctx loc x1 k in
501✔
162
        (* Format.printf "trying  cons cell succeeded\n%!"; *)
163
        k
361✔
164
      | _ ->
51✔
165
        (* Format.printf "failing elem of cons cell\n%!"; *)
166
        fail loc "::")
167
;;
168

169
let list (T fel) =
170
  let rec helper acc ctx loc xs k =
2✔
171
    match xs with
6✔
172
    | [] -> k (List.rev acc)
2✔
173
    | h :: tl ->
4✔
174
      (match fel ctx loc h Fun.id with
175
       | x -> helper (x :: acc) ctx loc tl k)
4✔
176
  in
177
  T (fun ctx loc xs k -> helper [] ctx loc xs k)
2✔
178
;;
179

180
let none =
181
  T
182
    (fun ctx loc x k ->
183
      match x with
72✔
184
      | None ->
72✔
185
        ctx.matched <- ctx.matched + 1;
186
        k
187
      | _ -> fail loc "None")
×
188
;;
189

190
let some (T f0) =
191
  T
8,210✔
192
    (fun ctx loc x k ->
193
      match x with
156✔
194
      | Some x0 ->
156✔
195
        ctx.matched <- ctx.matched + 1;
196
        let k = f0 ctx loc x0 k in
197
        k
73✔
198
      | _ -> fail loc "Some")
×
199
;;
200

201
let triple (T f1) (T f2) (T f3) =
202
  T
×
203
    (fun ctx loc (x1, x2, x3) k ->
204
      let k = f1 ctx loc x1 k in
×
205
      let k = f2 ctx loc x2 k in
×
206
      let k = f3 ctx loc x3 k in
×
207
      k)
×
208
;;
209

210
let alt (T f1) (T f2) =
211
  T
12,387✔
212
    (fun ctx loc x k ->
213
      let backup = save_context ctx in
41,891✔
214
      try f1 ctx loc x k with
822✔
215
      | e1 ->
41,069✔
216
        let m1 = save_context ctx in
217
        restore_context ctx backup;
41,069✔
218
        (try f2 ctx loc x k with
753✔
219
         | e2 ->
40,316✔
220
           let m2 = save_context ctx in
221
           if m1 >= m2
40,316✔
222
           then (
39,989✔
223
             restore_context ctx m1;
224
             raise e1)
39,989✔
225
           else raise e2))
327✔
226
;;
227

228
let ( ||| ) = alt
229
let map (T func) ~f = T (fun ctx loc x k -> func ctx loc x (f k))
×
230
let map' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (f loc k))
×
231
let map_result (T func) ~f = T (fun ctx loc x k -> f (func ctx loc x k))
×
232
let ( >>| ) t f = map t ~f
×
233
let map0 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (k f))
336✔
234
let map1 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a -> k (f a)))
606✔
235
let map2 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a b -> k (f a b)))
370✔
236
let map3 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a b c -> k (f a b c)))
57✔
237

238
let map4 (T func) ~f =
239
  T (fun ctx loc x k -> func ctx loc x (fun a b c d -> k (f a b c d)))
9✔
240
;;
241

242
let map5 (T func) ~f =
243
  T (fun ctx loc x k -> func ctx loc x (fun a b c d e -> k (f a b c d e)))
22✔
244
;;
245

246
let map6 (T func) ~f:fmap =
247
  T (fun ctx loc x k -> func ctx loc x (fun a b c d e f -> k (fmap a b c d e f)))
1✔
248
;;
249

250
let map7 (T func) ~f:fmap =
251
  T (fun ctx loc x k -> func ctx loc x (fun a b c d e f g -> k (fmap a b c d e f g)))
3✔
252
;;
253

254
let map0' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (k (f loc)))
×
255
let map1' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a -> k (f loc a)))
×
256
let map2' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a b -> k (f loc a b)))
×
257
let map_result (T func) ~f = T (fun ctx loc x k -> f (func ctx loc x k))
×
258
let alt_option some none = alt (map1 some ~f:(fun x -> Some x)) (map0 none ~f:None)
×
259

260
let many (T f) =
261
  T (fun ctx loc l k -> k (ListLabels.map l ~f:(fun x -> f ctx loc x (fun x -> x))))
×
262
;;
263

264
let loc (T f) = T (fun ctx _loc (x : _ Ppxlib.Loc.t) k -> f ctx x.loc x.txt k)
×
265
let pack0 t = map t ~f:(fun f -> f ())
×
266
let pack2 t = map t ~f:(fun f x y -> f (x, y))
×
267
let pack3 t = map t ~f:(fun f x y z -> f (x, y, z))
×
268

269
(* end of copy-paste from https://github.com/ocaml-ppx/ppxlib/blob/0.22.2/src/ast_pattern.ml *)
270
(* TODO: deal with licencing issues *)
271

272
let lident (T fident) =
273
  T
585✔
274
    (fun ctx loc x k ->
275
      match x with
136✔
276
      | Longident.Lident id ->
126✔
277
        ctx.matched <- ctx.matched + 1;
278
        k |> fident ctx loc id
279
      | _ -> fail loc "lident")
10✔
280
;;
281

282
let elongident (lident : Longident.t) =
283
  T
57✔
284
    (fun ctx loc x k ->
285
      if Stdlib.compare x lident = 0
183✔
286
      then (
15✔
287
        ctx.matched <- ctx.matched + 1;
288
        k)
289
      else fail loc "elongident")
168✔
290
;;
291

292
let path_pident (T fident) =
293
  T
×
294
    (fun ctx loc x k ->
295
      match x with
×
296
      | Path.Pident id ->
×
297
        ctx.matched <- ctx.matched + 1;
298
        k |> fident ctx loc id
299
      | _ -> fail loc (sprintf "path_pident"))
×
300
;;
301

302
let path xs =
303
  let rec helper ps ctx loc x k =
5,691✔
304
    let cmp_names l r =
13,444✔
305
      let ans = String.equal l r in
7,060✔
306
      (* printf "\t\tCompare names %s and %s:  %b\n%!" l r ans; *)
307
      ans
7,060✔
308
    in
309
    match x, ps with
310
    | Path.Pident id, [ id0 ] ->
117✔
311
      if cmp_names (Ident.name id) id0
117✔
312
      then (
110✔
313
        let () = ctx.matched <- ctx.matched + 1 in
314
        k)
315
      else fail loc "path"
7✔
316
    | Path.Pdot (next, id), id0 :: ids when cmp_names id id0 -> helper ids ctx loc next k
152✔
317
    | Path.Papply _, _ -> fail loc "path got Papply"
×
318
    | _ -> fail loc (sprintf "path %s" (String.concat "." xs))
13,175✔
319
  in
320
  T (helper (List.rev xs))
5,691✔
321
;;
322

323
let path_of_list = function
324
  | [] -> failwith "Bad argument: path_of_list"
×
325
  | s :: tl ->
2✔
326
    ListLabels.fold_left
327
      tl
328
      ~init:(Path.Pident (Ident.create_local s))
2✔
329
      ~f:(fun acc x -> Path.Pdot (acc, x))
4✔
330
;;
331

332
let%test_module " " =
333
  (module struct
334
    let names = [ "Stdlib!"; "List"; "length" ]
335

336
    [%%if ocaml_version < (5, 0, 0)]
337

338
    let pp_path = Path.print
339

340
    [%%else]
341

342
    let pp_path = Format_doc.compat Path.print
343

344
    [%%endif]
345

346
    let%test_unit _ =
347
      let old = !Clflags.unique_ids in
348
      Clflags.unique_ids := false;
349
      [%test_eq: Base.string]
1✔
350
        "Stdlib!.List.length"
351
        (asprintf "%a" pp_path (path_of_list names));
1✔
352
      Clflags.unique_ids := old
1✔
353
    ;;
354

355
    let%test _ =
356
      let noloc =
1✔
357
        Warnings.
358
          { loc_start = Lexing.dummy_pos; loc_end = Lexing.dummy_pos; loc_ghost = true }
359
      in
360
      parse (path names) noloc ~on_error:(fun _ -> false) (path_of_list names) true
×
361
    ;;
362
  end)
363
;;
364

365
open Typedtree
366

367
let econst (T f0) =
368
  T
×
369
    (fun ctx loc x k ->
370
      match x.exp_desc with
×
371
      | Texp_constant n ->
×
372
        ctx.matched <- ctx.matched + 1;
373
        f0 ctx loc n k
374
      | _ -> fail loc (sprintf "econst"))
×
375
;;
376

377
let eint (T f0) =
378
  T
470✔
379
    (fun ctx loc x k ->
380
      match x.exp_desc with
17✔
381
      | Texp_constant (Asttypes.Const_int n) ->
8✔
382
        ctx.matched <- ctx.matched + 1;
383
        f0 ctx loc n k
384
      | _ -> fail loc "eint")
9✔
385
;;
386

387
let estring =
388
  T
389
    (fun ctx loc x k ->
390
      match x.exp_desc with
15✔
391
      | Texp_constant (Asttypes.Const_string (s, _, None)) ->
15✔
392
        ctx.matched <- ctx.matched + 1;
393
        k s
394
      | _ -> fail loc "estring")
×
395
;;
396

397
let ebool =
398
  T
399
    (fun ctx loc x k ->
400
      match x.exp_desc with
95✔
401
      | Texp_construct ({ txt = Lident "true" }, _, []) ->
11✔
402
        ctx.matched <- ctx.matched + 1;
403
        k true
404
      | Texp_construct ({ txt = Lident "false" }, _, []) ->
8✔
405
        ctx.matched <- ctx.matched + 1;
406
        k false
407
      | _ -> fail loc (sprintf "ebool"))
76✔
408
;;
409

410
[%%if ocaml_version < (5, 0, 0)]
411

412
let tpat_var (T fname) =
413
  T
1,521✔
414
    (fun ctx loc x k ->
415
      match x.pat_desc with
51✔
416
      | Tpat_var (_, { txt }) ->
51✔
417
        ctx.matched <- ctx.matched + 1;
418
        k |> fname ctx loc txt
419
      | _ -> fail loc "tpat_var")
×
420
;;
421

422
let tpat_id (T fname) =
423
  T
1,893✔
424
    (fun ctx loc x k ->
425
      match x.pat_desc with
293✔
426
      | Tpat_var (id, { loc }) ->
232✔
427
        ctx.matched <- ctx.matched + 1;
428
        k |> fname ctx loc id
429
      | _ -> fail loc "tpat_var_id")
61✔
430
;;
431

432
[%%else]
433

434
let tpat_var (T fname) =
435
  T
436
    (fun (type kind) ctx loc (x : kind pattern_desc pattern_data) k ->
437
      match x.pat_desc with
438
      | Tpat_var (_, { txt }, _uid) ->
439
        ctx.matched <- ctx.matched + 1;
440
        k |> fname ctx loc txt
441
      | Tpat_value v ->
442
        (match (v :> pattern).pat_desc with
443
         | Tpat_var (_, { txt }, _uid) ->
444
           ctx.matched <- ctx.matched + 1;
445
           k |> fname ctx loc txt
446
         | _ -> fail loc "tpat_var")
447
      | _ -> fail loc "tpat_var")
448
;;
449

450
let tpat_id (T fname) =
451
  T
452
    (fun (type kind) ctx loc (x : kind pattern_desc pattern_data) k ->
453
      match x.pat_desc with
454
      | Typedtree.Tpat_value v ->
455
        (match (v :> pattern).pat_desc with
456
         | Tpat_var (id, { loc }, _uid) ->
457
           ctx.matched <- ctx.matched + 1;
458
           k |> fname ctx loc id
459
         | _ -> fail loc "tpat_id")
460
      | Tpat_var (id, { loc }, _uid) ->
461
        ctx.matched <- ctx.matched + 1;
462
        k |> fname ctx loc id
463
      | _ -> fail loc "tpat_id 2")
464
;;
465

466
[%%endif]
467

468
let tpat_constructor (T fname) (T fargs) =
469
  T
5,804✔
470
    (fun ctx loc x k ->
471
      match x.pat_desc with
84✔
472
      | Tpat_construct ({ txt }, _, args, _) ->
75✔
473
        ctx.matched <- ctx.matched + 1;
474
        k |> fname ctx loc txt |> fargs ctx loc args
66✔
475
      | _ -> fail loc "tpat_constructor")
9✔
476
;;
477

478
let tpat_tuple (T fargs) =
479
  T
×
480
    (fun ctx loc x k ->
481
      match x.pat_desc with
×
482
      | Tpat_tuple pats ->
×
483
        ctx.matched <- ctx.matched + 1;
484
        k |> fargs ctx loc pats
485
      | _ -> fail loc "tpat_tuple")
×
486
;;
487

488
let tpat_value (T fpat) =
489
  T
×
490
    (fun ctx loc x k ->
491
      match x.pat_desc with
×
492
      | Tpat_value arg ->
×
493
        let inner = (arg :> value pattern_desc pattern_data) in
494
        ctx.matched <- ctx.matched + 1;
495
        k |> fpat ctx loc inner
496
      | _ -> fail loc "tpat_value")
×
497
;;
498

499
let tpat_exception (T fpat) =
500
  T
×
501
    (fun ctx loc x k ->
502
      match x.pat_desc with
×
503
      | Tpat_exception exc ->
×
504
        ctx.matched <- ctx.matched + 1;
505
        k |> fpat ctx loc exc
506
      | _ -> fail loc "tpat_exception")
×
507
;;
508

509
let tpat_any =
510
  T
511
    (fun ctx loc x k ->
512
      match x.pat_desc with
3✔
513
      | Tpat_any ->
2✔
514
        ctx.matched <- ctx.matched + 1;
515
        k
516
      | _ -> fail loc "tpat_any")
1✔
517
;;
518

519
let texp_ident (T fpath) =
520
  T
14,736✔
521
    (fun ctx loc x k ->
522
      let __ _ = log "texp_ident %a\n%!" My_printtyped.expr x in
×
523
      match x.exp_desc with
524
      | Texp_ident (path, _, _) ->
11,727✔
525
        ctx.matched <- ctx.matched + 1;
526
        let ans = fpath ctx loc path k in
527
        log "texp_ident + %a\n%!" My_printtyped.expr x;
798✔
528
        ans
798✔
529
      | _ -> fail loc "texp_ident")
3,131✔
530
;;
531

532
let texp_ident_loc (T fpath) =
533
  T
1,249✔
534
    (fun ctx loc x k ->
535
      match x.exp_desc with
15✔
536
      | Texp_ident (path, _, _) ->
10✔
537
        ctx.matched <- ctx.matched + 1;
538
        k x.exp_loc |> fpath ctx loc path
10✔
539
      | _ -> fail loc "texp_ident")
5✔
540
;;
541

542
(* TODO(Kakadu): accept and Ident, and not a string *)
543
let pident (T fstr) =
544
  T
7,449✔
545
    (fun ctx loc x k ->
546
      match x with
211✔
547
      | Path.Pident id -> fstr ctx loc (Ident.name id) k
93✔
548
      | _ -> fail loc "pident")
118✔
549
;;
550

551
let texp_ident_typ (T fpath) (T ftyp) =
552
  T
284✔
553
    (fun ctx loc x k ->
554
      (* let __ _ = Format.printf "texp_ident_typ %a\n%!" MyPrinttyped.expr x in *)
555
      match x.exp_desc with
1,599✔
556
      | Texp_ident (path, _, typ) ->
829✔
557
        ctx.matched <- ctx.matched + 1;
558
        k |> fpath ctx loc path |> ftyp ctx loc typ.Types.val_type
437✔
559
      | _ -> fail loc "texp_ident_typ")
770✔
560
;;
561

562
[%%if ocaml_version < (5, 0, 0)]
563

564
let texp_assert (T fexp) =
565
  T
57✔
566
    (fun ctx loc x k ->
567
      match x.exp_desc with
1,459✔
568
      | Texp_assert e ->
1✔
569
        ctx.matched <- ctx.matched + 1;
570
        fexp ctx loc e k
571
      | _ -> fail loc "texp_assert")
1,458✔
572
;;
573

574
[%%else]
575

576
let texp_assert (T fexp) =
577
  T
578
    (fun ctx loc x k ->
579
       match x.exp_desc with
580
       | Texp_assert (e, _) ->
581
         ctx.matched <- ctx.matched + 1;
582
         fexp ctx loc e k
583
       | _ -> fail loc "texp_assert"
584
     : context -> Warnings.loc -> expression -> 'a -> 'b)
585
;;
586

587
[%%endif]
588

589
let texp_apply (T f0) (T args0) =
590
  T
5,980✔
591
    (fun ctx loc x k ->
592
      (* let __ _ = log "texp_apply %a\n%!" MyPrinttyped.expr x in *)
593
      match x.exp_desc with
25,719✔
594
      | Texp_apply (f, args) ->
3,584✔
595
        ctx.matched <- ctx.matched + 1;
596
        let ans = k |> f0 ctx loc f |> args0 ctx loc args in
73✔
597
        (* let _ = log "texp_apply + %a\n%!" MyPrinttyped.expr x in *)
598
        ans
43✔
599
      | _ -> fail loc "texp_apply")
22,135✔
600
;;
601

602
let texp_apply_nolabelled (T f0) (T args0) =
603
  let exception EarlyExit in
1,542✔
604
  T
605
    (fun ctx loc x k ->
606
      match x.exp_desc with
3,088✔
607
      | Texp_apply (f, args) ->
482✔
608
        ctx.matched <- ctx.matched + 1;
609
        let k = f0 ctx loc f k in
610
        (try
95✔
611
           let args =
612
             ListLabels.map args ~f:(function
613
               | Asttypes.Labelled _, _ | Asttypes.Optional _, _ | _, None ->
×
614
                 raise EarlyExit
615
               | _, Some x -> x)
206✔
616
           in
617
           args0 ctx loc args k
22✔
618
         with
619
         | EarlyExit -> fail loc "texp_apply: None among the arguments ")
2✔
620
      | _ -> fail loc "texp_apply")
2,606✔
621
;;
622

623
let texp_construct (T fpath) (T fcd) (T fargs) =
624
  T
218✔
625
    (fun ctx loc x k ->
626
      match x.exp_desc with
1,483✔
627
      | Texp_construct (path, cd, args) ->
192✔
628
        ctx.matched <- ctx.matched + 1;
629
        let k = fpath ctx loc path.txt k in
630
        k |> fcd ctx loc cd |> fargs ctx loc args
24✔
631
      | _ -> fail loc (sprintf "texp_construct"))
1,291✔
632
;;
633

634
let texp_assert_false () = texp_assert (texp_construct (lident (string "false")) drop nil)
57✔
635

636
let texp_let (T fvbs) (T fexpr) =
637
  T
1,472✔
638
    (fun ctx loc x k ->
639
      match x.exp_desc with
1,268✔
640
      | Texp_let (_flg, vbs, expr) ->
18✔
641
        ctx.matched <- ctx.matched + 1;
642
        k |> fvbs ctx loc vbs |> fexpr ctx loc expr
15✔
643
      | _ -> fail loc (sprintf "texp_let"))
1,250✔
644
;;
645

646
let nolabel =
647
  T
648
    (fun ctx loc x k ->
649
      match x with
255✔
650
      | Asttypes.Nolabel ->
236✔
651
        ctx.matched <- ctx.matched + 1;
652
        k
653
      | _ -> fail loc "nolabel")
19✔
654
;;
655

656
let labelled (T fstr) =
657
  T
57✔
658
    (fun ctx loc x k ->
659
      match x with
2✔
660
      | Asttypes.Labelled s ->
2✔
661
        ctx.matched <- ctx.matched + 1;
662
        k |> fstr ctx loc s
663
      | _ -> fail loc "labelled")
×
664
;;
665

666
let texp_apply1 f x = texp_apply f ((nolabel ** some x) ^:: nil)
3,408✔
667
let texp_apply2 f x y = texp_apply f ((nolabel ** some x) ^:: (nolabel ** some y) ^:: nil)
2,173✔
668

669
[%%if ocaml_version < (4, 11, 2)]
670

671
(* 4.10 *)
672
type case_val = Typedtree.case
673
type case_comp = Typedtree.case
674
type value_pat = pattern
675
type comp_pat = pattern
676

677
[%%else]
678

679
type case_val = value case
680
type case_comp = computation case
681
type value_pat = value pattern_desc pattern_data
682
type comp_pat = computation pattern_desc pattern_data
683

684
[%%endif]
685
[%%if ocaml_version < (5, 0, 0)]
686

687
let texp_function (T fcases) =
688
  T
×
689
    (fun ctx loc e k ->
690
      match e.exp_desc with
×
691
      | Texp_function { cases } ->
×
692
        ctx.matched <- ctx.matched + 1;
693
        k |> fcases ctx loc cases
694
      | _ -> fail loc "texp_function")
×
695
;;
696

697
let texp_function_body (T fargs) (T frhs) =
698
  let rec helper acc ctx loc e k =
6,802✔
699
    match e.exp_desc with
6,290✔
700
    | Texp_function
955✔
701
        { cases =
702
            [ { c_lhs = { pat_desc = Tpat_var (pid, _); pat_loc; _ }
703
              ; c_rhs
704
              ; c_guard = None
705
              }
706
            ]
707
        ; arg_label
708
        ; partial = Total
709
        } -> helper ((arg_label, (pid, pat_loc)) :: acc) ctx loc c_rhs k
710
    | _ when [] = acc -> fail loc "texp_function_body"
4,638✔
711
    | _ -> k |> fargs ctx loc (List.rev acc) |> frhs ctx loc e
609✔
712
  in
713
  T (helper [])
6,802✔
714
;;
715

716
let texp_function_cases
717
  :  ((Asttypes.arg_label * (Ident.t * Location.t)) list, 'a, 'b) t
718
  -> (value case list, 'b, 'c) t
719
  -> (expression, 'a, 'c) t
720
  =
721
  fun (T fargs) (T frhs) ->
722
  let rec helper acc ctx loc e k =
5,827✔
723
    match e.exp_desc with
4,741✔
724
    | Typedtree.Texp_function
566✔
725
        { cases =
726
            [ { c_lhs = { pat_desc = Tpat_var (pid, tag); _ }; c_rhs; c_guard = _ } ]
727
        ; arg_label
728
        ; partial = Total
729
        } -> helper ((arg_label, (pid, tag.loc)) :: acc) ctx loc c_rhs k
730
    | Texp_function { cases = _ :: _ :: _ as cases; _ } ->
91✔
731
      k |> fargs ctx loc (List.rev acc) |> frhs ctx loc cases
62✔
732
    | _ -> fail loc "texp_function_cases"
4,084✔
733
  in
734
  T (helper [])
5,827✔
735
;;
736

737
[%%else]
738

739
let texp_function_cases (T fparam) (T fcases) =
740
  T
741
    (fun ctx loc e k ->
742
      match e.exp_desc with
743
      | Texp_function (params, Tfunction_cases cases) ->
744
        ctx.matched <- ctx.matched + 1;
745
        k
746
        |> fparam
747
             ctx
748
             loc
749
             (List.map (fun p -> p.Typedtree.fp_arg_label, (p.fp_param, p.fp_loc)) params)
750
        |> fcases ctx loc cases.cases
751
      | _ -> fail loc "texp_function")
752
;;
753

754
let texp_function_body (T fparam) (T fcases) =
755
  T
756
    (fun ctx loc e k ->
757
      match e.exp_desc with
758
      | Typedtree.Texp_function (params, Tfunction_body e) ->
759
        ctx.matched <- ctx.matched + 1;
760
        k
761
        |> fparam
762
             ctx
763
             loc
764
             (List.map (fun p -> p.fp_arg_label, (p.fp_param, p.fp_loc)) params)
765
        |> fcases ctx loc e
766
      | _ -> fail loc "texp_function")
767
;;
768

769
[%%endif]
770

771
let case (T pat) (T guard) (T rhs) =
772
  T
7,330✔
773
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
774
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
53✔
775
;;
776

777
let ccase (T pat) (T guard) (T rhs) =
778
  T
×
779
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
780
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
×
781
;;
782

783
[%%if ocaml_version < (5, 0, 0)]
784

785
let texp_match (T fexpr) (T fcomp_cases) (T fval_cases) =
786
  let rec split (type _a) (comps, vals) (cases : _ case list) =
2,731✔
787
    let _ : case_comp list = comps in
215✔
788
    let _ : case_val list = vals in
789
    let wrap (type a) comps vals : a case -> case_comp list * case_val list =
790
      let _ : case_comp list = comps in
147✔
791
      let _ : case_val list = vals in
792
      fun case ->
793
        match case with
147✔
794
        | { c_lhs = { pat_desc = Tpat_value p }; _ } ->
142✔
795
          ( comps
796
          , { c_lhs = (p :> pattern); c_rhs = case.c_rhs; c_guard = case.c_guard } :: vals
797
          )
798
        | { c_lhs = { pat_desc = Tpat_any }; _ } -> comps, (case :> case_val) :: vals
×
799
        | { c_lhs = { pat_desc = Tpat_var _ }; _ } -> comps, (case :> case_val) :: vals
×
800
        | { c_lhs = { pat_desc = Tpat_alias _ }; _ } -> comps, (case :> case_val) :: vals
×
801
        | { c_lhs = { pat_desc = Tpat_constant _ }; _ } ->
×
802
          comps, (case :> case_val) :: vals
803
        | { c_lhs = { pat_desc = Tpat_construct _ }; _ } ->
×
804
          comps, (case :> case_val) :: vals
805
        | { c_lhs = { pat_desc = Tpat_variant _ }; _ } ->
×
806
          comps, (case :> case_val) :: vals
807
        | { c_lhs = { pat_desc = Tpat_record _ }; _ } -> comps, (case :> case_val) :: vals
×
808
        | { c_lhs = { pat_desc = Tpat_array _ }; _ } -> comps, (case :> case_val) :: vals
×
809
        | { c_lhs = { pat_desc = Tpat_lazy _ }; _ } -> comps, (case :> case_val) :: vals
×
810
        (* | { c_lhs = { pat_desc = Tpat_value _ }; _ } -> (case :> case_comp) :: comps, vals *)
811
        | { c_lhs = { pat_desc = Tpat_exception _ }; _ } ->
3✔
812
          (case :> case_comp) :: comps, vals
813
        | { c_lhs = { pat_desc = Tpat_or _ }; _ } ->
2✔
814
          (* TODO(Kakadu): What to do here? We need to look deeply into or-pattern to understand where to place it?
815
            See issue #76
816
          *)
817
          (* failwith "Or-patterns are not yet implemented" *)
818
          comps, vals
819
        | { c_lhs; _ } ->
×
820
          (* Format.eprintf "%a\n%!" My_printtyped.pattern c_lhs; *)
821
          Format.eprintf
822
            "Unsupported pattern: tag = %d, is_block = %b\n"
823
            Obj.(tag @@ repr c_lhs)
×
824
            Obj.(is_block @@ repr c_lhs);
×
825
          assert false
×
826
    in
827
    match cases with
828
    | h :: tl -> split (wrap comps vals h) tl
147✔
829
    | [] -> List.rev comps, List.rev vals
68✔
830
  in
831
  T
832
    (fun ctx loc e k ->
833
      match e.exp_desc with
2,950✔
834
      | Texp_match (e, cases, _) ->
68✔
835
        ctx.matched <- ctx.matched + 1;
836
        let comp_cases, val_cases = split ([], []) cases in
837
        (* log
838
           "There are %d comp cases and %d val cases"
839
           (List.length comp_cases)
840
           (List.length val_cases); *)
841
        k
68✔
842
        |> fexpr ctx loc e
843
        |> fcomp_cases ctx loc comp_cases
62✔
844
        |> fval_cases ctx loc val_cases
62✔
845
      | _ -> fail loc "texp_match")
2,882✔
846
;;
847

848
[%%else]
849

850
let texp_match (T fexpr) (T fcomp_cases) (T fval_cases) =
851
  T
852
    (fun ctx loc e k ->
853
      match e.Typedtree.exp_desc with
854
      | Texp_match (e, ccases, vcases, _) ->
855
        let ccases, vcases =
856
          List.fold_left
857
            (fun (cacc, vacc) c ->
858
              match c.c_lhs.pat_desc with
859
              | Tpat_value v ->
860
                cacc, { c with c_lhs = (v :> value general_pattern) } :: vacc
861
              | _ -> cacc, vacc)
862
            ([], vcases)
863
            ccases
864
        in
865
        ctx.matched <- ctx.matched + 1;
866
        k |> fexpr ctx loc e |> fcomp_cases ctx loc ccases |> fval_cases ctx loc vcases
867
      | _ -> fail loc "texp_match")
868
;;
869

870
[%%endif]
871

872
let texp_ite (T pred) (T fthen) (T felse) =
873
  T
684✔
874
    (fun ctx loc e k ->
875
      match e.exp_desc with
7,907✔
876
      | Texp_ifthenelse (p, thenb, elseb) ->
185✔
877
        ctx.matched <- ctx.matched + 1;
878
        k |> pred ctx loc p |> fthen ctx loc thenb |> felse ctx loc elseb
77✔
879
      | _ -> fail loc "texp_ite")
7,722✔
880
;;
881

882
[%%if ocaml_version < (5, 0, 0)]
883

884
let texp_try (T fexpr) (T fcases) =
885
  T
57✔
886
    (fun ctx loc e k ->
887
      match e.exp_desc with
1,461✔
888
      | Texp_try (e, cases) ->
3✔
889
        ctx.matched <- ctx.matched + 1;
890
        k |> fexpr ctx loc e |> fcases ctx loc cases
3✔
891
      | _ -> fail loc "texp_try")
1,458✔
892
;;
893

894
[%%else]
895

896
let texp_try (T fexpr) (T fcases) =
897
  T
898
    (fun ctx loc e k ->
899
      match e.exp_desc with
900
      | Typedtree.Texp_try (e, cases, _) ->
901
        (* TODO: support effects *)
902
        ctx.matched <- ctx.matched + 1;
903
        k |> fexpr ctx loc e |> fcases ctx loc cases
904
      | _ -> fail loc "texp_try")
905
;;
906

907
[%%endif]
908

909
let texp_record (T fext) (T ffields) =
910
  T
1,469✔
911
    (fun ctx loc e k ->
912
      match e.exp_desc with
1,469✔
913
      | Texp_record { fields; extended_expression; _ } ->
19✔
914
        ctx.matched <- ctx.matched + 1;
915
        k |> fext ctx loc extended_expression |> ffields ctx loc fields
19✔
916
      | _ -> fail loc "texp_record")
1,450✔
917
;;
918

919
let texp_field (T fexpr) (T fdesc) =
920
  T
56✔
921
    (fun ctx loc e k ->
922
      match e.exp_desc with
51✔
923
      | Texp_field (e, _, desc) ->
17✔
924
        ctx.matched <- ctx.matched + 1;
925
        k |> fexpr ctx loc e |> fdesc ctx loc desc
17✔
926
      | _ -> fail loc "texp_field")
34✔
927
;;
928

929
let label_desc (T fname) =
930
  T
112✔
931
    (fun ctx loc e k ->
932
      match e with
95✔
933
      | { Types.lbl_name; _ } ->
95✔
934
        ctx.matched <- ctx.matched + 1;
935
        k |> fname ctx loc lbl_name)
936
;;
937

938
let rld_kept =
939
  T
940
    (fun ctx loc e k ->
941
      match e with
56✔
942
      | Kept _ ->
×
943
        ctx.matched <- ctx.matched + 1;
944
        k
945
      | _ -> fail loc "rld_kept")
56✔
946
;;
947

948
let rld_overriden (T flident) (T fexpr) =
949
  T
112✔
950
    (fun ctx loc e k ->
951
      match e with
95✔
952
      | Overridden ({ txt = lident }, e) ->
95✔
953
        ctx.matched <- ctx.matched + 1;
954
        k |> flident ctx loc lident |> fexpr ctx loc e
85✔
955
      | _ -> fail loc "rld_overriden")
×
956
;;
957

958
let value_binding (T fpat) (T fexpr) =
959
  T
1,576✔
960
    (fun ctx loc { vb_pat; vb_expr } k ->
961
      ctx.matched <- ctx.matched + 1;
119✔
962
      k |> fpat ctx loc vb_pat |> fexpr ctx loc vb_expr)
117✔
963
;;
964

965
(*   let hack0 (T path0) =
966
     T
967
     (fun ctx loc x k ->
968
     match x.Types.val_type.Types.desc with
969
     | Tconstr (path, [], _) ->
970
     ctx.matched <- ctx.matched + 1;
971
     path0 ctx loc path k
972
     | _ -> fail loc "hack0")
973
     ;;
974

975
     let hack1 ?(on_vd = drop) (T path0) =
976
     T
977
     (fun ctx loc x k ->
978
     match x.exp_desc with
979
     | Texp_ident (path, _, vd) ->
980
     ctx.matched <- ctx.matched + 1;
981
     let (T fvd) = on_vd in
982
     k |> path0 ctx loc path |> fvd ctx loc vd
983
     | _ -> fail loc "texp_ident")
984
     ;;
985

986
     let __ path = hack1 __ path *)
987
let rec core_typ (T ftexpr) = T (fun ctx loc x k -> ftexpr ctx loc x.ctyp_type k)
169✔
988

989
let rec typ_constr (T fpath) (T fargs) =
990
  let rec helper ctx loc x k =
673✔
991
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
992
    match Types.get_desc x with
2,374✔
993
    | Tconstr (path, args, _) ->
1,277✔
994
      ctx.matched <- ctx.matched + 1;
995
      k |> fpath ctx loc path |> fargs ctx loc args
205✔
996
    | Tlink arg -> helper ctx loc arg k
×
997
    | _ -> fail loc "typ_constr"
1,097✔
998
  in
999
  T helper
1000
;;
1001

1002
let rec typ_arrow (T l) (T r) =
1003
  let rec helper ctx loc x k =
344✔
1004
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
1005
    match Types.get_desc x with
22✔
1006
    | Tarrow (_, tl, tr, _) ->
22✔
1007
      ctx.matched <- ctx.matched + 1;
1008
      k |> l ctx loc tl |> r ctx loc tr
22✔
1009
    | _ -> fail loc "typ_arrow"
×
1010
  in
1011
  T helper
1012
;;
1013

1014
let typ_kind_abstract =
1015
  T
1016
    (fun ctx loc x k ->
1017
      match x with
67✔
1018
      | Typedtree.Ttype_abstract ->
8✔
1019
        ctx.matched <- ctx.matched + 1;
1020
        k
1021
      | _ -> fail loc "typ_kind_abstract")
59✔
1022
;;
1023

1024
let typ_kind_open =
1025
  T
1026
    (fun ctx loc x k ->
1027
      match x with
67✔
1028
      | Typedtree.Ttype_open ->
×
1029
        ctx.matched <- ctx.matched + 1;
1030
        k
1031
      | _ -> fail loc "typ_kind_open")
67✔
1032
;;
1033

1034
let typ_kind_variant =
1035
  T
1036
    (fun ctx loc x k ->
1037
      match x with
59✔
1038
      | Typedtree.Ttype_variant _ ->
49✔
1039
        ctx.matched <- ctx.matched + 1;
1040
        k
1041
      | _ -> fail loc "typ_kind_variant")
10✔
1042
;;
1043

1044
let typ_kind_record (T flabels) =
1045
  T
55✔
1046
    (fun ctx loc x k ->
1047
      match x with
10✔
1048
      | Typedtree.Ttype_record labels ->
10✔
1049
        ctx.matched <- ctx.matched + 1;
1050
        k |> flabels ctx loc labels
1051
      | _ -> fail loc "typ_kind_record")
×
1052
;;
1053

1054
(* Structure *)
1055

1056
let tstr_attribute (T fattr) =
1057
  T
40✔
1058
    (fun ctx loc str k ->
1059
      match str.str_desc with
40✔
1060
      | Tstr_attribute attr ->
15✔
1061
        ctx.matched <- ctx.matched + 1;
1062
        k |> fattr ctx loc attr
1063
      | _ -> fail loc "tstr_attribute")
25✔
1064
;;
1065

1066
let tsig_attribute (T fattr) =
1067
  T
3✔
1068
    (fun ctx loc str k ->
1069
      match str.sig_desc with
3✔
1070
      | Tsig_attribute attr ->
2✔
1071
        ctx.matched <- ctx.matched + 1;
1072
        k |> fattr ctx loc attr
1073
      | _ -> fail loc "tsig_attribute")
1✔
1074
;;
1075

1076
let tsig_val_name (T fname) =
1077
  T
×
1078
    (fun ctx loc str k ->
1079
      match str.sig_desc with
×
1080
      | Tsig_value { val_id = txt } ->
×
1081
        ctx.matched <- ctx.matched + 1;
1082
        k |> fname ctx loc txt
1083
      | _ -> fail loc "tsig_val_name")
×
1084
;;
1085

1086
let attribute (T fname) (T fpayload) =
1087
  T
43✔
1088
    (fun ctx loc attr k ->
1089
      let open Parsetree in
17✔
1090
      k |> fname ctx loc attr.attr_name.txt |> fpayload ctx loc attr.attr_payload)
17✔
1091
;;
1092

1093
let payload_stru (T fstru) =
1094
  T
43✔
1095
    (fun ctx loc x k ->
1096
      match x with
17✔
1097
      | Parsetree.PStr stru -> k |> fstru ctx loc stru
17✔
1098
      | _ -> fail loc "payload_stru")
×
1099
;;
1100

1101
let pstr_eval (T f) =
1102
  T
43✔
1103
    (fun ctx loc x k ->
1104
      match x.Parsetree.pstr_desc with
17✔
1105
      | Parsetree.Pstr_eval (e, _) -> k |> f ctx loc e
17✔
1106
      | _ -> fail loc "pstr_eval")
×
1107
;;
1108

1109
let pexp_constant (T f) =
1110
  T
43✔
1111
    (fun ctx loc e k ->
1112
      match e.Parsetree.pexp_desc with
17✔
1113
      | Parsetree.Pexp_constant e -> k |> f ctx loc e
13✔
1114
      | _ -> fail loc "pexp_constant")
4✔
1115
;;
1116

1117
[%%if ocaml_version < (5, 0, 0)]
1118

1119
let pexp_function_cases (T fargs) (T fcases) =
1120
  let open Parsetree in
3✔
1121
  let rec helper acc ctx loc x k =
1122
    match x.pexp_desc with
9✔
1123
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
6✔
1124
    | Pexp_function cases -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc cases
3✔
1125
    | _ -> fail loc "pexp_function_cases"
×
1126
  in
1127
  T (helper [])
3✔
1128
;;
1129

1130
let pexp_function_body (T fargs) (T fcases) =
1131
  let open Parsetree in
1✔
1132
  let rec helper acc ctx loc x k =
1133
    match x.pexp_desc with
3✔
1134
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
2✔
1135
    | _ -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc x
1✔
1136
  in
1137
  T (helper [])
1✔
1138
;;
1139

1140
let pconst_string (T fstring) =
1141
  T
43✔
1142
    (fun ctx loc x k ->
1143
      match x with
13✔
1144
      | Parsetree.Pconst_string (s, _, _) -> k |> fstring ctx loc s
13✔
1145
      | _ -> fail loc "pconst_string")
×
1146
;;
1147

1148
[%%else]
1149

1150
let pexp_function_body (T fargs) (T fbody) =
1151
  let open Parsetree in
1152
  T
1153
    (fun ctx loc x k ->
1154
      match x.pexp_desc with
1155
      | Pexp_function (params, _, Pfunction_body e) ->
1156
        let args =
1157
          List.map
1158
            (fun p ->
1159
              match p.pparam_desc with
1160
              | Pparam_val (Nolabel, _, pat) -> pat
1161
              | Pparam_newtype _ | _ -> fail loc "pexp_function_body: params")
1162
            params
1163
        in
1164
        k |> fargs ctx loc args |> fbody ctx loc e
1165
      | _ -> fail loc "pexp_function_body")
1166
;;
1167

1168
let pexp_function_cases (T fargs) (T fcases) =
1169
  let open Parsetree in
1170
  T
1171
    (fun ctx loc x k ->
1172
      match x.pexp_desc with
1173
      | Pexp_function (params, _, Pfunction_cases (cases, _, _)) ->
1174
        let args =
1175
          List.map
1176
            (fun p ->
1177
              match p.pparam_desc with
1178
              | Pparam_val (Nolabel, _, pat) -> pat
1179
              | Pparam_newtype _ | _ -> fail loc "pexp_function_cases: params")
1180
            params
1181
        in
1182
        k |> fargs ctx loc args |> fcases ctx loc cases
1183
      | _ -> fail loc "pexp_function_cases")
1184
;;
1185

1186
let pconst_string (T fstring) =
1187
  T
1188
    (fun ctx loc x k ->
1189
      match x.Parsetree.pconst_desc with
1190
      | Parsetree.Pconst_string (s, _, _) -> k |> fstring ctx loc s
1191
      | _ -> fail loc "pconst_string")
1192
;;
1193

1194
[%%endif]
1195

1196
let pexp_apply (T f) (T fargs) =
1197
  let open Parsetree in
1✔
1198
  let helper ctx loc x k =
1199
    match x.pexp_desc with
1✔
1200
    | Pexp_apply (efun, eargs) -> k |> f ctx loc efun |> fargs ctx loc eargs
1✔
1201
    | _ -> fail loc "pexp_apply"
×
1202
  in
1203
  T helper
1204
;;
1205

1206
let tstr_docattr on_str =
1207
  tstr_attribute
40✔
1208
    (attribute
40✔
1209
       drop
1210
       (payload_stru (pstr_eval (pexp_constant (pconst_string on_str)) ^:: nil)))
40✔
1211
;;
1212

1213
let tsig_docattr on_str =
1214
  tsig_attribute
3✔
1215
    (attribute
3✔
1216
       drop
1217
       (payload_stru (pstr_eval (pexp_constant (pconst_string on_str)) ^:: nil)))
3✔
1218
;;
1219

1220
type context = Ast_pattern0.context
1221

1222
let of_func f = T f
×
1223
let to_func (T f) = f
×
1224
let fail = fail
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc