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

Kakadu / zanuda / 18

17 Sep 2025 05:06PM UTC coverage: 85.847% (-1.5%) from 87.346%
18

push

github

Kakadu
Repair coverage testing

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

2032 of 2367 relevant lines covered (85.85%)

477.23 hits per line

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

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

3
(** Copyright 2021-2024, 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,750✔
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,245✔
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
121,489✔
44
let restore_context ctx backup = ctx.matched <- backup
79,955✔
45
let incr_matched c = c.matched <- c.matched + 1
3,934✔
46

47
let parse (T f) loc ?on_error x k =
48
  try f { matched = 0 } loc x k with
1,416✔
49
  | Expected (loc, expected) ->
30,259✔
50
    (match on_error with
51
     | None -> Location.raise_errorf ~loc "%s expected" expected
×
52
     | Some f -> f expected)
30,259✔
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,697✔
66
      k x)
2,697✔
67
;;
68

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

77
let pair (T f1) (T f2) =
78
  T
3,797✔
79
    (fun ctx loc (x1, x2) k ->
80
      let k = f1 ctx loc x1 k in
401✔
81
      let k = f2 ctx loc x2 k in
382✔
82
      k)
259✔
83
;;
84

85
let ( ** ) = pair
86

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

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

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

112
let int v = cst ~to_string:Int.to_string v
480✔
113
let char v = cst ~to_string:(Printf.sprintf "%C") v
×
114
let string v = cst ~to_string:(Printf.sprintf "%S") v
708✔
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%!";
401✔
145
      match x with
401✔
146
      | [] ->
304✔
147
        ctx.matched <- ctx.matched + 1;
148
        k
149
      | _ -> fail loc "[]")
97✔
150
;;
151

152
let ( ^:: ) (T f0) (T f1) =
153
  T
7,452✔
154
    (fun ctx loc x k ->
155
      match x with
615✔
156
      | x0 :: x1 ->
576✔
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
486✔
162
        (* Format.printf "trying  cons cell succeeded\n%!"; *)
163
        k
343✔
164
      | _ ->
39✔
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
71✔
184
      | None ->
71✔
185
        ctx.matched <- ctx.matched + 1;
186
        k
187
      | _ -> fail loc "None")
×
188
;;
189

190
let some (T f0) =
191
  T
2,535✔
192
    (fun ctx loc x k ->
193
      match x with
143✔
194
      | Some x0 ->
143✔
195
        ctx.matched <- ctx.matched + 1;
196
        let k = f0 ctx loc x0 k in
197
        k
68✔
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
9,635✔
212
    (fun ctx loc x k ->
213
      let backup = save_context ctx in
41,234✔
214
      try f1 ctx loc x k with
743✔
215
      | e1 ->
40,491✔
216
        let m1 = save_context ctx in
217
        restore_context ctx backup;
40,491✔
218
        (try f2 ctx loc x k with
727✔
219
         | e2 ->
39,764✔
220
           let m2 = save_context ctx in
221
           if m1 >= m2
39,764✔
222
           then (
39,464✔
223
             restore_context ctx m1;
224
             raise e1)
39,464✔
225
           else raise e2))
300✔
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))
171✔
234
let map1 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a -> k (f a)))
647✔
235
let map2 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a b -> k (f a b)))
353✔
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)))
2✔
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
649✔
274
    (fun ctx loc x k ->
275
      match x with
140✔
276
      | Longident.Lident id ->
130✔
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
206✔
286
      then (
19✔
287
        ctx.matched <- ctx.matched + 1;
288
        k)
289
      else fail loc "elongident")
187✔
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,771✔
304
    let cmp_names l r =
13,455✔
305
      let ans = String.equal l r in
7,319✔
306
      (* printf "\t\tCompare names %s and %s:  %b\n%!" l r ans; *)
307
      ans
7,319✔
308
    in
309
    let __ _ = Format.printf "path = %a\n%!" Path.print x in
×
310
    match x, ps with
311
    | Path.Pident id, [ id0 ] ->
115✔
312
      if cmp_names (Ident.name id) id0
115✔
313
      then (
108✔
314
        let () = ctx.matched <- ctx.matched + 1 in
315
        k)
316
      else fail loc "path"
7✔
317
    | Path.Pdot (next, id), id0 :: ids when cmp_names id id0 -> helper ids ctx loc next k
150✔
318
    | Path.Papply _, _ -> fail loc "path got Papply"
×
319
    | _ -> fail loc (sprintf "path %s" (String.concat "." xs))
13,190✔
320
  in
321
  T (helper (List.rev xs))
5,771✔
322
;;
323

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

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

337
    let%test_unit _ =
338
      let old = !Clflags.unique_ids in
339
      Clflags.unique_ids := false;
340
      [%test_eq: Base.string]
1✔
341
        "Stdlib!.List.length"
342
        (asprintf "%a" Path.print (path_of_list names));
1✔
343
      Clflags.unique_ids := old
1✔
344
    ;;
345

346
    let%test _ =
347
      let noloc =
1✔
348
        Warnings.
349
          { loc_start = Lexing.dummy_pos; loc_end = Lexing.dummy_pos; loc_ghost = true }
350
      in
351
      parse (path names) noloc ~on_error:(fun _ -> false) (path_of_list names) true
×
352
    ;;
353
  end)
354
;;
355

356
open Typedtree
357

358
let econst (T f0) =
359
  T
×
360
    (fun ctx loc x k ->
361
      match x.exp_desc with
×
362
      | Texp_constant n ->
×
363
        ctx.matched <- ctx.matched + 1;
364
        f0 ctx loc n k
365
      | _ -> fail loc (sprintf "econst"))
×
366
;;
367

368
let eint (T f0) =
369
  T
480✔
370
    (fun ctx loc x k ->
371
      match x.exp_desc with
16✔
372
      | Texp_constant (Asttypes.Const_int n) ->
8✔
373
        ctx.matched <- ctx.matched + 1;
374
        f0 ctx loc n k
375
      | _ -> fail loc "eint")
8✔
376
;;
377

378
let estring =
379
  T
380
    (fun ctx loc x k ->
381
      match x.exp_desc with
19✔
382
      | Texp_constant (Asttypes.Const_string (s, _, None)) ->
19✔
383
        ctx.matched <- ctx.matched + 1;
384
        k s
385
      | _ -> fail loc "estring")
×
386
;;
387

388
let ebool =
389
  T
390
    (fun ctx loc x k ->
391
      match x.exp_desc with
92✔
392
      | Texp_construct ({ txt = Lident "true" }, _, []) ->
11✔
393
        ctx.matched <- ctx.matched + 1;
394
        k true
395
      | Texp_construct ({ txt = Lident "false" }, _, []) ->
8✔
396
        ctx.matched <- ctx.matched + 1;
397
        k false
398
      | _ -> fail loc (sprintf "ebool"))
73✔
399
;;
400

401
let tpat_var (T fname) =
402
  T
117✔
403
    (fun ctx loc x k ->
404
      match x.pat_desc with
61✔
405
      | Tpat_var (_, { txt }) ->
61✔
406
        ctx.matched <- ctx.matched + 1;
407
        k |> fname ctx loc txt
408
      | _ -> fail loc "tpat_var")
×
409
;;
410

411
let tpat_id (T fname) =
412
  T
1,782✔
413
    (fun ctx loc x k ->
414
      match x.pat_desc with
99✔
415
      | Tpat_var (id, { loc }) ->
86✔
416
        ctx.matched <- ctx.matched + 1;
417
        k |> fname ctx loc id
418
      | _ -> fail loc "tpat_var_id")
13✔
419
;;
420

421
let tpat_constructor (T fname) (T fargs) =
422
  T
472✔
423
    (fun ctx loc x k ->
424
      match x.pat_desc with
78✔
425
      | Tpat_construct ({ txt }, _, args, _) ->
68✔
426
        ctx.matched <- ctx.matched + 1;
427
        k |> fname ctx loc txt |> fargs ctx loc args
55✔
428
      | _ -> fail loc "tpat_constructor")
10✔
429
;;
430

431
let tpat_tuple (T fargs) =
432
  T
×
433
    (fun ctx loc x k ->
434
      match x.pat_desc with
×
435
      | Tpat_tuple pats ->
×
436
        ctx.matched <- ctx.matched + 1;
437
        k |> fargs ctx loc pats
438
      | _ -> fail loc "tpat_tuple")
×
439
;;
440

441
let tpat_value (T fpat) =
442
  T
×
443
    (fun ctx loc x k ->
444
      match x.pat_desc with
×
445
      | Tpat_value arg ->
×
446
        let inner = (arg :> value pattern_desc pattern_data) in
447
        ctx.matched <- ctx.matched + 1;
448
        k |> fpat ctx loc inner
449
      | _ -> fail loc "tpat_value")
×
450
;;
451

452
let tpat_exception (T fpat) =
453
  T
×
454
    (fun ctx loc x k ->
455
      match x.pat_desc with
×
456
      | Tpat_exception exc ->
×
457
        ctx.matched <- ctx.matched + 1;
458
        k |> fpat ctx loc exc
459
      | _ -> fail loc "tpat_exception")
×
460
;;
461

462
let tpat_any =
463
  T
464
    (fun ctx loc x k ->
465
      match x.pat_desc with
3✔
466
      | Tpat_any ->
2✔
467
        ctx.matched <- ctx.matched + 1;
468
        k
469
      | _ -> fail loc "tpat_any")
1✔
470
;;
471

472
let texp_ident (T fpath) =
473
  T
7,798✔
474
    (fun ctx loc x k ->
475
      let __ _ = log "texp_ident %a\n%!" My_printtyped.expr x in
×
476
      match x.exp_desc with
477
      | Texp_ident (path, _, _) ->
11,723✔
478
        ctx.matched <- ctx.matched + 1;
479
        let ans = fpath ctx loc path k in
480
        log "texp_ident + %a\n%!" My_printtyped.expr x;
844✔
481
        ans
844✔
482
      | _ -> fail loc "texp_ident")
3,197✔
483
;;
484

485
let texp_ident_loc (T fpath) =
486
  T
1,321✔
487
    (fun ctx loc x k ->
488
      match x.exp_desc with
18✔
489
      | Texp_ident (path, _, _) ->
12✔
490
        ctx.matched <- ctx.matched + 1;
491
        k x.exp_loc |> fpath ctx loc path
12✔
492
      | _ -> fail loc "texp_ident")
6✔
493
;;
494

495
(* TODO(Kakadu): accept and Ident, and not a string *)
496
let pident (T fstr) =
497
  T
291✔
498
    (fun ctx loc x k ->
499
      match x with
203✔
500
      | Path.Pident id -> fstr ctx loc (Ident.name id) k
81✔
501
      | _ -> fail loc "pident")
122✔
502
;;
503

504
let texp_ident_typ (T fpath) (T ftyp) =
505
  T
284✔
506
    (fun ctx loc x k ->
507
      (* let __ _ = Format.printf "texp_ident_typ %a\n%!" MyPrinttyped.expr x in *)
508
      match x.exp_desc with
1,655✔
509
      | Texp_ident (path, _, typ) ->
854✔
510
        ctx.matched <- ctx.matched + 1;
511
        k |> fpath ctx loc path |> ftyp ctx loc typ.Types.val_type
466✔
512
      | _ -> fail loc "texp_ident_typ")
801✔
513
;;
514

515
let texp_assert (T fexp) =
516
  T
57✔
517
    (fun ctx loc x k ->
518
      match x.exp_desc with
1,519✔
519
      | Texp_assert e ->
1✔
520
        ctx.matched <- ctx.matched + 1;
521
        fexp ctx loc e k
522
      | _ -> fail loc "texp_assert")
1,518✔
523
;;
524

525
let texp_apply (T f0) (T args0) =
526
  T
1,707✔
527
    (fun ctx loc x k ->
528
      (* let __ _ = log "texp_apply %a\n%!" MyPrinttyped.expr x in *)
529
      match x.exp_desc with
26,580✔
530
      | Texp_apply (f, args) ->
3,532✔
531
        ctx.matched <- ctx.matched + 1;
532
        let ans = k |> f0 ctx loc f |> args0 ctx loc args in
65✔
533
        (* let _ = log "texp_apply + %a\n%!" MyPrinttyped.expr x in *)
534
        ans
41✔
535
      | _ -> fail loc "texp_apply")
23,048✔
536
;;
537

538
let texp_apply_nolabelled (T f0) (T args0) =
539
  let exception EarlyExit in
1,650✔
540
  T
541
    (fun ctx loc x k ->
542
      match x.exp_desc with
3,215✔
543
      | Texp_apply (f, args) ->
480✔
544
        ctx.matched <- ctx.matched + 1;
545
        let k = f0 ctx loc f k in
546
        (try
97✔
547
           let args =
548
             ListLabels.map args ~f:(function
549
               | Asttypes.Labelled _, _ | Asttypes.Optional _, _ | _, None ->
×
550
                 raise EarlyExit
551
               | _, Some x -> x)
212✔
552
           in
553
           args0 ctx loc args k
22✔
554
         with
555
         | EarlyExit -> fail loc "texp_apply: None among the arguments ")
2✔
556
      | _ -> fail loc "texp_apply")
2,735✔
557
;;
558

559
let texp_construct (T fpath) (T fcd) (T fargs) =
560
  T
234✔
561
    (fun ctx loc x k ->
562
      match x.exp_desc with
1,543✔
563
      | Texp_construct (path, cd, args) ->
215✔
564
        ctx.matched <- ctx.matched + 1;
565
        let k = fpath ctx loc path.txt k in
566
        k |> fcd ctx loc cd |> fargs ctx loc args
28✔
567
      | _ -> fail loc (sprintf "texp_construct"))
1,328✔
568
;;
569

570
let texp_assert_false () = texp_assert (texp_construct (lident (string "false")) drop nil)
57✔
571

572
let texp_let (T fvbs) (T fexpr) =
573
  T
1,531✔
574
    (fun ctx loc x k ->
575
      match x.exp_desc with
1,328✔
576
      | Texp_let (_flg, vbs, expr) ->
18✔
577
        ctx.matched <- ctx.matched + 1;
578
        k |> fvbs ctx loc vbs |> fexpr ctx loc expr
15✔
579
      | _ -> fail loc (sprintf "texp_let"))
1,310✔
580
;;
581

582
let nolabel =
583
  T
584
    (fun ctx loc x k ->
585
      match x with
246✔
586
      | Asttypes.Nolabel ->
227✔
587
        ctx.matched <- ctx.matched + 1;
588
        k
589
      | _ -> fail loc "nolabel")
19✔
590
;;
591

592
let labelled (T fstr) =
593
  T
57✔
594
    (fun ctx loc x k ->
595
      match x with
2✔
596
      | Asttypes.Labelled s ->
2✔
597
        ctx.matched <- ctx.matched + 1;
598
        k |> fstr ctx loc s
599
      | _ -> fail loc "labelled")
×
600
;;
601

602
let texp_apply1 f x = texp_apply f ((nolabel ** some x) ^:: nil)
537✔
603
let texp_apply2 f x y = texp_apply f ((nolabel ** some x) ^:: (nolabel ** some y) ^:: nil)
771✔
604

605
[%%if ocaml_version < (4, 11, 2)]
606

607
(* 4.10 *)
608
type case_val = Typedtree.case
609
type case_comp = Typedtree.case
610
type value_pat = pattern
611
type comp_pat = pattern
612

613
[%%else]
614

615
type case_val = value case
616
type case_comp = computation case
617
type value_pat = value pattern_desc pattern_data
618
type comp_pat = computation pattern_desc pattern_data
619

620
[%%endif]
621
[%%if ocaml_version < (5, 0, 0)]
622

623
let texp_function (T fcases) =
624
  T
57✔
625
    (fun ctx loc e k ->
626
      match e.exp_desc with
2✔
627
      | Texp_function { cases } ->
2✔
628
        ctx.matched <- ctx.matched + 1;
629
        k |> fcases ctx loc cases
630
      | _ -> fail loc "texp_function")
×
631
;;
632

633
let texp_function_body (T fargs) (T frhs) =
634
  let rec helper acc ctx loc e k =
5,604✔
635
    match e.exp_desc with
6,570✔
636
    | Texp_function
969✔
637
        { cases =
638
            [ { c_lhs = { pat_desc = Tpat_var (pid, _); pat_loc; _ }
639
              ; c_rhs
640
              ; c_guard = None
641
              }
642
            ]
643
        ; arg_label
644
        ; partial = Total
645
        } -> helper ((arg_label, (pid, pat_loc)) :: acc) ctx loc c_rhs k
646
    | _ when [] = acc -> fail loc "texp_function_body"
4,902✔
647
    | _ -> k |> fargs ctx loc (List.rev acc) |> frhs ctx loc e
606✔
648
  in
649
  T (helper [])
5,604✔
650
;;
651

652
let texp_function_cases (T fargs) (T frhs) =
653
  let rec helper acc ctx loc e k =
3,112✔
654
    match e.exp_desc with
3,257✔
655
    | Typedtree.Texp_function
334✔
656
        { cases =
657
            [ { c_lhs = { pat_desc = Tpat_var (pid, tag); _ }; c_rhs; c_guard = _ } ]
658
        ; arg_label
659
        ; partial = Total
660
        } -> helper ((arg_label, (pid, tag)) :: acc) ctx loc c_rhs k
661
    (* | _ when [] = acc -> fail loc "texp_function_cases" *)
662
    | Texp_function { cases = _ :: _ :: _ as cases; _ } ->
61✔
663
      k |> fargs ctx loc (List.rev acc) |> frhs ctx loc cases
36✔
664
    | _ -> fail loc "texp_function_cases"
2,862✔
665
  in
666
  T (helper [])
3,112✔
667
;;
668

669
[%%else]
670
[%%endif]
671

672
let case (T pat) (T guard) (T rhs) =
673
  T
586✔
674
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
675
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
52✔
676
;;
677

678
let ccase (T pat) (T guard) (T rhs) =
679
  T
×
680
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
681
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
×
682
;;
683

684
let texp_match (T fexpr) (T fcomp_cases) (T fval_cases) =
685
  let rec split (type _a) (comps, vals) (cases : _ case list) =
1,494✔
686
    let _ : case_comp list = comps in
257✔
687
    let _ : case_val list = vals in
688
    let wrap (type a) comps vals : a case -> case_comp list * case_val list =
689
      let _ : case_comp list = comps in
177✔
690
      let _ : case_val list = vals in
691
      fun case ->
692
        match case with
177✔
693
        | { c_lhs = { pat_desc = Tpat_value p }; _ } ->
174✔
694
          ( comps
695
          , { c_lhs = (p :> pattern); c_rhs = case.c_rhs; c_guard = case.c_guard } :: vals
696
          )
697
        | { c_lhs = { pat_desc = Tpat_any }; _ } -> comps, (case :> case_val) :: vals
×
698
        | { c_lhs = { pat_desc = Tpat_var _ }; _ } -> comps, (case :> case_val) :: vals
×
699
        | { c_lhs = { pat_desc = Tpat_alias _ }; _ } -> comps, (case :> case_val) :: vals
×
700
        | { c_lhs = { pat_desc = Tpat_constant _ }; _ } ->
×
701
          comps, (case :> case_val) :: vals
702
        | { c_lhs = { pat_desc = Tpat_construct _ }; _ } ->
×
703
          comps, (case :> case_val) :: vals
704
        | { c_lhs = { pat_desc = Tpat_variant _ }; _ } ->
×
705
          comps, (case :> case_val) :: vals
706
        | { c_lhs = { pat_desc = Tpat_record _ }; _ } -> comps, (case :> case_val) :: vals
×
707
        | { c_lhs = { pat_desc = Tpat_array _ }; _ } -> comps, (case :> case_val) :: vals
×
708
        | { c_lhs = { pat_desc = Tpat_lazy _ }; _ } -> comps, (case :> case_val) :: vals
×
709
        (* | { c_lhs = { pat_desc = Tpat_value _ }; _ } -> (case :> case_comp) :: comps, vals *)
710
        | { c_lhs = { pat_desc = Tpat_exception _ }; _ } ->
3✔
711
          (case :> case_comp) :: comps, vals
712
        | { c_lhs = { pat_desc = Tpat_or _ }; _ } ->
×
713
          failwith "Or-patterns are not yet implemented"
714
        | { c_lhs; _ } ->
×
715
          (* Format.eprintf "%a\n%!" My_printtyped.pattern c_lhs; *)
716
          Format.eprintf
717
            "Unsupported pattern: tag = %d, is_block = %b\n"
718
            Obj.(tag @@ repr c_lhs)
×
719
            Obj.(is_block @@ repr c_lhs);
×
720
          assert false
×
721
    in
722
    match cases with
723
    | h :: tl -> split (wrap comps vals h) tl
177✔
724
    | [] -> List.rev comps, List.rev vals
80✔
725
  in
726
  T
727
    (fun ctx loc e k ->
728
      match e.exp_desc with
3,120✔
729
      | Texp_match (e, cases, _) ->
80✔
730
        ctx.matched <- ctx.matched + 1;
731
        let comp_cases, val_cases = split ([], []) cases in
732
        (* log
733
           "There are %d comp cases and %d val cases"
734
           (List.length comp_cases)
735
           (List.length val_cases); *)
736
        k
80✔
737
        |> fexpr ctx loc e
738
        |> fcomp_cases ctx loc comp_cases
73✔
739
        |> fval_cases ctx loc val_cases
73✔
740
      | _ -> fail loc "texp_match")
3,040✔
741
;;
742

743
let texp_ite (T pred) (T fthen) (T felse) =
744
  T
684✔
745
    (fun ctx loc e k ->
746
      match e.exp_desc with
7,914✔
747
      | Texp_ifthenelse (p, thenb, elseb) ->
177✔
748
        ctx.matched <- ctx.matched + 1;
749
        k |> pred ctx loc p |> fthen ctx loc thenb |> felse ctx loc elseb
73✔
750
      | _ -> fail loc "texp_ite")
7,737✔
751
;;
752

753
let texp_try (T fexpr) (T fcases) =
754
  T
57✔
755
    (fun ctx loc e k ->
756
      match e.exp_desc with
1,521✔
757
      | Texp_try (e, cases) ->
3✔
758
        ctx.matched <- ctx.matched + 1;
759
        k |> fexpr ctx loc e |> fcases ctx loc cases
3✔
760
      | _ -> fail loc "texp_try")
1,518✔
761
;;
762

763
let texp_record (T fext) (T ffields) =
764
  T
1,529✔
765
    (fun ctx loc e k ->
766
      match e.exp_desc with
1,529✔
767
      | Texp_record { fields; extended_expression; _ } ->
19✔
768
        ctx.matched <- ctx.matched + 1;
769
        k |> fext ctx loc extended_expression |> ffields ctx loc fields
19✔
770
      | _ -> fail loc "texp_record")
1,510✔
771
;;
772

773
let texp_field (T fexpr) (T fdesc) =
774
  T
56✔
775
    (fun ctx loc e k ->
776
      match e.exp_desc with
51✔
777
      | Texp_field (e, _, desc) ->
17✔
778
        ctx.matched <- ctx.matched + 1;
779
        k |> fexpr ctx loc e |> fdesc ctx loc desc
17✔
780
      | _ -> fail loc "texp_field")
34✔
781
;;
782

783
let label_desc (T fname) =
784
  T
112✔
785
    (fun ctx loc e k ->
786
      match e with
95✔
787
      | { Types.lbl_name; _ } ->
95✔
788
        ctx.matched <- ctx.matched + 1;
789
        k |> fname ctx loc lbl_name)
790
;;
791

792
let rld_kept =
793
  T
794
    (fun ctx loc e k ->
795
      match e with
56✔
796
      | Kept _ ->
×
797
        ctx.matched <- ctx.matched + 1;
798
        k
799
      | _ -> fail loc "rld_kept")
56✔
800
;;
801

802
let rld_overriden (T flident) (T fexpr) =
803
  T
112✔
804
    (fun ctx loc e k ->
805
      match e with
95✔
806
      | Overridden ({ txt = lident }, e) ->
95✔
807
        ctx.matched <- ctx.matched + 1;
808
        k |> flident ctx loc lident |> fexpr ctx loc e
85✔
809
      | _ -> fail loc "rld_overriden")
×
810
;;
811

812
let value_binding (T fpat) (T fexpr) =
813
  T
1,651✔
814
    (fun ctx loc { vb_pat; vb_expr } k ->
815
      ctx.matched <- ctx.matched + 1;
135✔
816
      k |> fpat ctx loc vb_pat |> fexpr ctx loc vb_expr)
133✔
817
;;
818

819
(*   let hack0 (T path0) =
820
     T
821
     (fun ctx loc x k ->
822
     match x.Types.val_type.Types.desc with
823
     | Tconstr (path, [], _) ->
824
     ctx.matched <- ctx.matched + 1;
825
     path0 ctx loc path k
826
     | _ -> fail loc "hack0")
827
     ;;
828

829
     let hack1 ?(on_vd = drop) (T path0) =
830
     T
831
     (fun ctx loc x k ->
832
     match x.exp_desc with
833
     | Texp_ident (path, _, vd) ->
834
     ctx.matched <- ctx.matched + 1;
835
     let (T fvd) = on_vd in
836
     k |> path0 ctx loc path |> fvd ctx loc vd
837
     | _ -> fail loc "texp_ident")
838
     ;;
839

840
     let __ path = hack1 __ path *)
841
let rec core_typ (T ftexpr) = T (fun ctx loc x k -> ftexpr ctx loc x.ctyp_type k)
169✔
842

843
let rec typ_constr (T fpath) (T fargs) =
844
  let rec helper ctx loc x k =
673✔
845
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
846
    match Types.get_desc x with
2,544✔
847
    | Tconstr (path, args, _) ->
1,355✔
848
      ctx.matched <- ctx.matched + 1;
849
      k |> fpath ctx loc path |> fargs ctx loc args
205✔
850
    | Tlink arg -> helper ctx loc arg k
×
851
    | _ -> fail loc "typ_constr"
1,189✔
852
  in
853
  T helper
854
;;
855

856
let rec typ_arrow (T l) (T r) =
857
  let rec helper ctx loc x k =
344✔
858
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
859
    match Types.get_desc x with
22✔
860
    | Tarrow (_, tl, tr, _) ->
22✔
861
      ctx.matched <- ctx.matched + 1;
862
      k |> l ctx loc tl |> r ctx loc tr
22✔
863
    | _ -> fail loc "typ_arrow"
×
864
  in
865
  T helper
866
;;
867

868
(* Structure *)
869

870
let tstr_attribute (T fattr) =
871
  T
×
872
    (fun ctx loc str k ->
873
      match str.str_desc with
×
874
      | Tstr_attribute attr ->
×
875
        ctx.matched <- ctx.matched + 1;
876
        k |> fattr ctx loc attr
877
      | _ -> fail loc "tstr_attribute")
×
878
;;
879

880
let tsig_attribute (T fattr) =
881
  T
×
882
    (fun ctx loc str k ->
883
      match str.sig_desc with
×
884
      | Tsig_attribute attr ->
×
885
        ctx.matched <- ctx.matched + 1;
886
        k |> fattr ctx loc attr
887
      | _ -> fail loc "tsig_attribute")
×
888
;;
889

890
let tsig_val_name (T fname) =
891
  T
×
892
    (fun ctx loc str k ->
893
      match str.sig_desc with
×
894
      | Tsig_value { val_id = txt } ->
×
895
        ctx.matched <- ctx.matched + 1;
896
        k |> fname ctx loc txt
897
      | _ -> fail loc "tsig_val_name")
×
898
;;
899

900
let attribute (T fname) (T fpayload) =
901
  T
×
902
    (fun ctx loc attr k ->
903
      let open Parsetree in
×
904
      k |> fname ctx loc attr.attr_name.txt |> fpayload ctx loc attr.attr_payload)
×
905
;;
906

907
let pexp_function_cases (T fargs) (T fcases) =
908
  let open Parsetree in
3✔
909
  let rec helper acc ctx loc x k =
910
    match x.pexp_desc with
9✔
911
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
6✔
912
    | Pexp_function cases -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc cases
3✔
913
    | _ -> fail loc "pexp_function_cases"
×
914
  in
915
  T (helper [])
3✔
916
;;
917

918
let pexp_function_body (T fargs) (T fcases) =
919
  let open Parsetree in
1✔
920
  let rec helper acc ctx loc x k =
921
    match x.pexp_desc with
3✔
922
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
2✔
923
    | _ -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc x
1✔
924
  in
925
  T (helper [])
1✔
926
;;
927

928
let pexp_apply (T f) (T fargs) =
929
  let open Parsetree in
1✔
930
  let helper ctx loc x k =
931
    match x.pexp_desc with
1✔
932
    | Pexp_apply (efun, eargs) -> k |> f ctx loc efun |> fargs ctx loc eargs
1✔
933
    | _ -> fail loc "pexp_apply"
×
934
  in
935
  T helper
936
;;
937

938
let tstr_docattr (T f) =
939
  T
40✔
940
    (fun ctx loc subj k ->
941
      let open Parsetree in
40✔
942
      match subj.str_desc with
943
      | Tstr_attribute
13✔
944
          { attr_payload =
945
              Parsetree.PStr
946
                [ { pstr_desc =
947
                      Pstr_eval
948
                        ( { pexp_desc = Pexp_constant (Pconst_string (docstr, _, None)) }
949
                        , _ )
950
                  }
951
                ]
952
          } ->
953
        ctx.matched <- ctx.matched + 1;
954
        k |> f ctx loc docstr
955
      | _ -> fail loc "tstr_docattr")
27✔
956
;;
957

958
let tsig_docattr (T f) =
959
  T
3✔
960
    (fun ctx loc subj k ->
961
      let open Parsetree in
3✔
962
      match subj.sig_desc with
963
      | Tsig_attribute
×
964
          { attr_payload =
965
              Parsetree.PStr
966
                [ { pstr_desc =
967
                      Pstr_eval
968
                        ( { pexp_desc = Pexp_constant (Pconst_string (docstr, _, None)) }
969
                        , _ )
970
                  }
971
                ]
972
          } ->
973
        ctx.matched <- ctx.matched + 1;
974
        k |> f ctx loc docstr
975
      | _ -> fail loc "tsig_docattr")
3✔
976
;;
977

978
type context = Ast_pattern0.context
979

980
let of_func f = T f
×
981
let to_func (T f) = f
×
982
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