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

Kakadu / zanuda / 83

30 Jun 2026 07:08PM UTC coverage: 85.004% (+0.06%) from 84.943%
83

push

github

Kakadu
Fix compilation errors after rebase

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

6 of 6 new or added lines in 1 file covered. (100.0%)

17 existing lines in 2 files now uncovered.

2256 of 2654 relevant lines covered (85.0%)

565.59 hits per line

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

76.06
/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))
78,711✔
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,299✔
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
137,286✔
44
let restore_context ctx backup = ctx.matched <- backup
90,335✔
45
let incr_matched c = c.matched <- c.matched + 1
4,569✔
46

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

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

77
let pair (T f1) (T f2) =
78
  T
10,453✔
79
    (fun ctx loc (x1, x2) k ->
80
      let k = f1 ctx loc x1 k in
423✔
81
      let k = f2 ctx loc x2 k in
404✔
82
      k)
275✔
83
;;
84

85
let ( ** ) = pair
86

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

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

101
let ( +?? ) (T fargs) msg =
102
  T
×
103
    (fun ctx loc e k ->
104
      try fargs ctx loc e k with
×
105
      | Ast_pattern0.Expected (loc, _) -> fail loc msg)
×
106
;;
107

108
let cst ~to_string ?(equal = Stdlib.( = )) v =
6,613✔
109
  T
6,613✔
110
    (fun ctx loc x k ->
111
      if equal x v
509✔
112
      then (
215✔
113
        incr_matched ctx;
114
        (* printf "cst succeeded for %s\n%!" (to_string v); *)
115
        k)
215✔
116
      else fail loc (to_string v))
294✔
117
;;
118

119
let int v = cst ~to_string:Int.to_string v
500✔
120
let char v = cst ~to_string:(Printf.sprintf "%C") v
×
121
let string v = cst ~to_string:(Printf.sprintf "%S") v
6,113✔
122
let float v = cst ~to_string:Float.to_string v
×
123
let int32 v = cst ~to_string:Int32.to_string v
×
124
let int64 v = cst ~to_string:Int64.to_string v
×
125
let nativeint v = cst ~to_string:Nativeint.to_string v
×
126
let bool v = cst ~to_string:Bool.to_string v
×
127

128
let false_ =
129
  T
130
    (fun ctx loc x k ->
131
      match x with
×
132
      | false ->
×
133
        ctx.matched <- ctx.matched + 1;
134
        k
135
      | _ -> fail loc "false")
×
136
;;
137

138
let true_ =
139
  T
140
    (fun ctx loc x k ->
141
      match x with
×
142
      | true ->
×
143
        ctx.matched <- ctx.matched + 1;
144
        k
145
      | _ -> fail loc "true")
×
146
;;
147

148
let nil =
149
  T
150
    (fun ctx loc x k ->
151
      log "trying [] \n%!";
484✔
152
      match x with
484✔
153
      | [] ->
381✔
154
        ctx.matched <- ctx.matched + 1;
155
        k
156
      | _ -> fail loc "[]")
103✔
157
;;
158

159
let ( ^:: ) (T f0) (T f1) =
160
  T
25,139✔
161
    (fun ctx loc x k ->
162
      match x with
754✔
163
      | x0 :: x1 ->
695✔
164
        ctx.matched <- ctx.matched + 1;
165
        (* Format.printf "trying elem of cons cell\n%!"; *)
166
        let k = f0 ctx loc x0 k in
167
        (* Format.printf "trying tail of cons cell\n%!"; *)
168
        let k = f1 ctx loc x1 k in
587✔
169
        (* Format.printf "trying  cons cell succeeded\n%!"; *)
170
        k
432✔
171
      | _ ->
59✔
172
        (* Format.printf "failing elem of cons cell\n%!"; *)
173
        fail loc "::")
174
;;
175

176
let list (T fel) =
177
  let rec helper acc ctx loc xs k =
2✔
178
    match xs with
6✔
179
    | [] -> k (List.rev acc)
2✔
180
    | h :: tl ->
4✔
181
      (match fel ctx loc h Fun.id with
182
       | x -> helper (x :: acc) ctx loc tl k)
4✔
183
  in
184
  T (fun ctx loc xs k -> helper [] ctx loc xs k)
2✔
185
;;
186

187
let none =
188
  T
189
    (fun ctx loc x k ->
190
      match x with
76✔
191
      | None ->
76✔
192
        ctx.matched <- ctx.matched + 1;
193
        k
194
      | _ -> fail loc "None")
×
195
;;
196

197
let some (T f0) =
198
  T
252✔
199
    (fun ctx loc x k ->
200
      match x with
58✔
201
      | Some x0 ->
58✔
202
        ctx.matched <- ctx.matched + 1;
203
        let k = f0 ctx loc x0 k in
204
        k
4✔
205
      | _ -> fail loc "Some")
×
206
;;
207

208
let triple (T f1) (T f2) (T f3) =
209
  T
×
210
    (fun ctx loc (x1, x2, x3) k ->
211
      let k = f1 ctx loc x1 k in
×
212
      let k = f2 ctx loc x2 k in
×
213
      let k = f3 ctx loc x3 k in
×
214
      k)
×
215
;;
216

217
let alt (T f1) (T f2) =
218
  T
13,572✔
219
    (fun ctx loc x k ->
220
      let backup = save_context ctx in
46,595✔
221
      try f1 ctx loc x k with
859✔
222
      | e1 ->
45,736✔
223
        let m1 = save_context ctx in
224
        restore_context ctx backup;
45,736✔
225
        (try f2 ctx loc x k with
781✔
226
         | e2 ->
44,955✔
227
           let m2 = save_context ctx in
228
           if m1 >= m2
44,955✔
229
           then (
44,599✔
230
             restore_context ctx m1;
231
             raise e1)
44,599✔
232
           else raise e2))
356✔
233
;;
234

235
let ( ||| ) = alt
236

237
let conde = function
238
  | [] -> fail Location.none "Bad argument"
×
239
  | h :: tl -> List.fold_left ( ||| ) h tl
31✔
240
;;
241

242
let map (T func) ~f = T (fun ctx loc x k -> func ctx loc x (f k))
×
243
let map' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (f loc k))
×
244
let map_result (T func) ~f = T (fun ctx loc x k -> f (func ctx loc x k))
×
245
let ( >>| ) t f = map t ~f
×
246
let map0 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (k f))
372✔
247
let map1 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a -> k (f a)))
615✔
248
let map2 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a b -> k (f a b)))
383✔
249
let map3 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a b c -> k (f a b c)))
61✔
250

251
let map4 (T func) ~f =
252
  T (fun ctx loc x k -> func ctx loc x (fun a b c d -> k (f a b c d)))
11✔
253
;;
254

255
let map5 (T func) ~f =
256
  T (fun ctx loc x k -> func ctx loc x (fun a b c d e -> k (f a b c d e)))
22✔
257
;;
258

259
let map6 (T func) ~f:fmap =
260
  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✔
261
;;
262

263
let map7 (T func) ~f:fmap =
264
  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✔
265
;;
266

267
let map0' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (k (f loc)))
×
268
let map1' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a -> k (f loc a)))
×
269
let map2' (T func) ~f = T (fun ctx loc x k -> func ctx loc x (fun a b -> k (f loc a b)))
×
270
let map_result (T func) ~f = T (fun ctx loc x k -> f (func ctx loc x k))
×
271
let alt_option some none = alt (map1 some ~f:(fun x -> Some x)) (map0 none ~f:None)
×
272

273
let many (T f) =
274
  T (fun ctx loc l k -> k (ListLabels.map l ~f:(fun x -> f ctx loc x (fun x -> x))))
×
275
;;
276

277
let loc (T f) = T (fun ctx _loc (x : _ Ppxlib.Loc.t) k -> f ctx x.loc x.txt k)
×
278
let pack0 t = map t ~f:(fun f -> f ())
×
279
let pack2 t = map t ~f:(fun f x y -> f (x, y))
×
280
let pack3 t = map t ~f:(fun f x y z -> f (x, y, z))
×
281

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

285
let lident (T fident) =
286
  T
734✔
287
    (fun ctx loc x k ->
288
      match x with
262✔
289
      | Longident.Lident id ->
251✔
290
        ctx.matched <- ctx.matched + 1;
291
        k |> fident ctx loc id
292
      | _ -> fail loc "lident")
11✔
293
;;
294

295
let elongident (lident : Longident.t) =
296
  T
×
297
    (fun ctx loc x k ->
298
      if Stdlib.compare x lident = 0
×
299
      then (
×
300
        ctx.matched <- ctx.matched + 1;
301
        k)
302
      else fail loc "elongident")
×
303
;;
304

305
[%%if ocaml_version < (5, 4, 0)]
306

307
let ldot_wrapper = Fun.id
308

309
[%%endif]
310
[%%if ocaml_version >= (5, 5, 0)]
311

312
let ldot_wrapper { txt; _ } = txt
313

314
[%%endif]
315

316
let ldot (T fl) (T fname) =
317
  T
63✔
318
    (fun ctx loc x k ->
319
      match x with
233✔
320
      | Longident.Ldot (ident, name) ->
117✔
321
        ctx.matched <- ctx.matched + 1;
322
        k |> fl ctx loc (ldot_wrapper ident) |> fname ctx loc (ldot_wrapper name)
116✔
323
      | _ -> fail loc "ldot")
116✔
324
;;
325

326
let path_pident (T fident) =
327
  T
2✔
328
    (fun ctx loc x k ->
329
      match x with
2✔
330
      | Path.Pident id ->
1✔
331
        ctx.matched <- ctx.matched + 1;
332
        k |> fident ctx loc id
333
      | _ -> fail loc "path_pident")
1✔
334
;;
335

336
let path xs =
337
  let rec helper ps ctx loc x k =
6,139✔
338
    let cmp_names l r =
15,023✔
339
      let ans = String.equal l r in
8,312✔
340
      (* printf "\t\tCompare names %s and %s:  %b\n%!" l r ans; *)
341
      ans
8,312✔
342
    in
343
    match x, ps with
344
    | Path.Pident id, [ id0 ] ->
128✔
345
      if cmp_names (Ident.name id) id0
128✔
346
      then (
120✔
347
        let () = ctx.matched <- ctx.matched + 1 in
348
        k)
349
      else fail loc "path"
8✔
350
    | Path.Pdot (next, id), id0 :: ids when cmp_names id id0 -> helper ids ctx loc next k
167✔
351
    | Path.Papply _, _ -> fail loc "path got Papply"
×
352
    | _ -> fail loc (sprintf "path %s" (String.concat "." xs))
14,728✔
353
  in
354
  T (helper (List.rev xs))
6,139✔
355
;;
356

357
let path_of_list = function
358
  | [] -> failwith "Bad argument: path_of_list"
1✔
359
  | s :: tl ->
2✔
360
    ListLabels.fold_left
361
      tl
362
      ~init:(Path.Pident (Ident.create_local s))
2✔
363
      ~f:(fun acc x -> Path.Pdot (acc, x))
4✔
364
;;
365

366
let%test_module " " =
367
  (module struct
368
    [@@@coverage off]
369

370
    let names = [ "Stdlib!"; "List"; "length" ]
371

372
    [%%if ocaml_version < (5, 0, 0)]
373

374
    let pp_path = Path.print
375

376
    [%%else]
377

378
    let pp_path = Format_doc.compat Path.print
379

380
    [%%endif]
381

382
    let%test_unit _ =
383
      let old = !Clflags.unique_ids in
384
      Clflags.unique_ids := false;
385
      [%test_eq: Base.string]
386
        "Stdlib!.List.length"
387
        (asprintf "%a" pp_path (path_of_list names));
388
      Clflags.unique_ids := old
389
    ;;
390

391
    let%test _ =
392
      let noloc =
393
        Warnings.
394
          { loc_start = Lexing.dummy_pos; loc_end = Lexing.dummy_pos; loc_ghost = true }
395
      in
396
      parse (path names) noloc ~on_error:(fun _ -> false) (path_of_list names) true
397
    ;;
398
  end)
399
;;
400

401
open Typedtree
402

403
let econst (T f0) =
404
  T
2✔
405
    (fun ctx loc x k ->
406
      match x.exp_desc with
2✔
407
      | Texp_constant n ->
2✔
408
        ctx.matched <- ctx.matched + 1;
409
        f0 ctx loc n k
410
      | _ -> fail loc (sprintf "econst"))
×
411
;;
412

413
let eint (T f0) =
414
  T
500✔
415
    (fun ctx loc x k ->
416
      match x.exp_desc with
17✔
417
      | Texp_constant (Asttypes.Const_int n) ->
8✔
418
        ctx.matched <- ctx.matched + 1;
419
        f0 ctx loc n k
420
      | _ -> fail loc "eint")
9✔
421
;;
422

423
let estring =
424
  T
425
    (fun ctx loc x k ->
426
      match x.exp_desc with
24✔
427
      | Texp_constant (Asttypes.Const_string (s, _, None)) ->
24✔
428
        ctx.matched <- ctx.matched + 1;
429
        k s
430
      | _ -> fail loc "estring")
×
431
;;
432

433
let ebool =
434
  T
435
    (fun ctx loc x k ->
436
      match x.exp_desc with
90✔
437
      | Texp_construct ({ txt = Lident "true" }, _, []) ->
11✔
438
        ctx.matched <- ctx.matched + 1;
439
        k true
440
      | Texp_construct ({ txt = Lident "false" }, _, []) ->
7✔
441
        ctx.matched <- ctx.matched + 1;
442
        k false
443
      | _ -> fail loc (sprintf "ebool"))
72✔
444
;;
445

446
[%%if ocaml_version < (5, 0, 0)]
447

448
let tpat_var (T fname) =
449
  T
1,709✔
450
    (fun ctx loc x k ->
451
      match x.pat_desc with
61✔
452
      | Tpat_var (_, { txt }) ->
61✔
453
        ctx.matched <- ctx.matched + 1;
454
        k |> fname ctx loc txt
455
      | _ -> fail loc "tpat_var")
×
456
;;
457

458
let tpat_id (T fname) =
459
  T
2,191✔
460
    (fun ctx loc x k ->
461
      match x.pat_desc with
380✔
462
      | Tpat_var (id, { loc }) ->
308✔
463
        ctx.matched <- ctx.matched + 1;
464
        k |> fname ctx loc id
465
      | _ -> fail loc "tpat_var_id")
72✔
466
;;
467

468
[%%else]
469

470
let tpat_var (T fname) =
471
  T
472
    (fun (type kind) ctx loc (x : kind pattern_desc pattern_data) k ->
473
      match x.pat_desc with
474
      | Tpat_var (_, { txt }, _uid) ->
475
        ctx.matched <- ctx.matched + 1;
476
        k |> fname ctx loc txt
477
      | Tpat_value v ->
478
        (match (v :> pattern).pat_desc with
479
         | Tpat_var (_, { txt }, _uid) ->
480
           ctx.matched <- ctx.matched + 1;
481
           k |> fname ctx loc txt
482
         | _ -> fail loc "tpat_var")
483
      | _ -> fail loc "tpat_var")
484
;;
485

486
let tpat_id (T fname) =
487
  T
488
    (fun (type kind) ctx loc (x : kind pattern_desc pattern_data) k ->
489
      match x.pat_desc with
490
      | Typedtree.Tpat_value v ->
491
        (match (v :> pattern).pat_desc with
492
         | Tpat_var (id, { loc }, _uid) ->
493
           ctx.matched <- ctx.matched + 1;
494
           k |> fname ctx loc id
495
         | _ -> fail loc "tpat_id")
496
      | Tpat_var (id, { loc }, _uid) ->
497
        ctx.matched <- ctx.matched + 1;
498
        k |> fname ctx loc id
499
      | _ -> fail loc "tpat_id 2")
500
;;
501

502
[%%endif]
503

504
let tpat_constructor (T fname) (T fargs) =
505
  T
6,128✔
506
    (fun ctx loc x k ->
507
      match x.pat_desc with
93✔
508
      | Tpat_construct ({ txt }, _, args, _) ->
80✔
509
        ctx.matched <- ctx.matched + 1;
510
        k |> fname ctx loc txt |> fargs ctx loc args
70✔
511
      | _ -> fail loc "tpat_constructor")
13✔
512
;;
513

514
[%%if ocaml_version < (5, 4, 0)]
515

516
let tpat_tuple (T fargs) =
517
  T
×
518
    (fun ctx loc x k ->
519
      match x.pat_desc with
×
520
      | Tpat_tuple pats ->
×
521
        ctx.matched <- ctx.matched + 1;
522
        k |> fargs ctx loc pats
523
      | _ -> fail loc "tpat_tuple")
×
524
;;
525

526
[%%else]
527

528
let tpat_tuple (T fargs) =
529
  T
530
    (fun ctx loc x k ->
531
      match x.pat_desc with
532
      | Tpat_tuple pats ->
533
        ctx.matched <- ctx.matched + 1;
534
        k |> fargs ctx loc (List.map snd pats)
535
      | _ -> fail loc "tpat_tuple")
536
;;
537

538
[%%endif]
539

540
let tpat_value (T fpat) =
541
  T
×
542
    (fun ctx loc x k ->
543
      match x.pat_desc with
×
544
      | Tpat_value arg ->
×
545
        let inner = (arg :> value pattern_desc pattern_data) in
546
        ctx.matched <- ctx.matched + 1;
547
        k |> fpat ctx loc inner
548
      | _ -> fail loc "tpat_value")
×
549
;;
550

551
let tpat_exception (T fpat) =
552
  T
×
553
    (fun ctx loc x k ->
554
      match x.pat_desc with
×
555
      | Tpat_exception exc ->
×
556
        ctx.matched <- ctx.matched + 1;
557
        k |> fpat ctx loc exc
558
      | _ -> fail loc "tpat_exception")
×
559
;;
560

561
let tpat_any =
562
  T
563
    (fun ctx loc x k ->
564
      match x.pat_desc with
3✔
565
      | Tpat_any ->
2✔
566
        ctx.matched <- ctx.matched + 1;
567
        k
568
      | _ -> fail loc "tpat_any")
1✔
569
;;
570

571
let texp_ident (T fpath) =
572
  T
16,107✔
573
    (fun ctx loc x k ->
574
      let __ _ = log "texp_ident %a\n%!" My_printtyped.expr x in
×
575
      match x.exp_desc with
576
      | Texp_ident (path, _, _) ->
13,019✔
577
        ctx.matched <- ctx.matched + 1;
578
        let ans = fpath ctx loc path k in
579
        log "texp_ident + %a\n%!" My_printtyped.expr x;
815✔
580
        ans
815✔
581
      | _ -> fail loc "texp_ident")
3,583✔
582
;;
583

584
let texp_ident_loc (T fpath) =
585
  T
1,427✔
586
    (fun ctx loc x k ->
587
      match x.exp_desc with
15✔
588
      | Texp_ident (path, _, _) ->
10✔
589
        ctx.matched <- ctx.matched + 1;
590
        k x.exp_loc |> fpath ctx loc path
10✔
591
      | _ -> fail loc "texp_ident")
5✔
592
;;
593

594
(* TODO(Kakadu): accept and Ident, and not a string *)
595
let pident (T fstr) =
596
  T
8,359✔
597
    (fun ctx loc x k ->
598
      match x with
234✔
599
      | Path.Pident id -> fstr ctx loc (Ident.name id) k
96✔
600
      | _ -> fail loc "pident")
138✔
601
;;
602

603
let texp_ident_typ (T fpath) (T ftyp) =
604
  T
316✔
605
    (fun ctx loc x k ->
606
      (* let __ _ = Format.printf "texp_ident_typ %a\n%!" MyPrinttyped.expr x in *)
607
      match x.exp_desc with
1,831✔
608
      | Texp_ident (path, _, typ) ->
926✔
609
        ctx.matched <- ctx.matched + 1;
610
        k |> fpath ctx loc path |> ftyp ctx loc typ.Types.val_type
488✔
611
      | _ -> fail loc "texp_ident_typ")
905✔
612
;;
613

614
[%%if ocaml_version < (5, 0, 0)]
615

616
let texp_assert (T fexp) =
617
  T
63✔
618
    (fun ctx loc x k ->
619
      match x.exp_desc with
1,637✔
620
      | Texp_assert e ->
1✔
621
        ctx.matched <- ctx.matched + 1;
622
        fexp ctx loc e k
623
      | _ -> fail loc "texp_assert")
1,636✔
624
;;
625

626
[%%else]
627

628
let texp_assert (T fexp) =
629
  T
630
    (fun ctx loc x k ->
631
       match x.exp_desc with
632
       | Texp_assert (e, _) ->
633
         ctx.matched <- ctx.matched + 1;
634
         fexp ctx loc e k
635
       | _ -> fail loc "texp_assert"
636
     : context -> Warnings.loc -> expression -> 'a -> 'b)
637
;;
638

639
[%%endif]
640

641
let texp_apply (T f0) (T args0) =
642
  T
6,641✔
643
    (fun ctx loc x k ->
644
      (* let __ _ = log "texp_apply %a\n%!" MyPrinttyped.expr x in *)
645
      match x.exp_desc with
28,701✔
646
      | Texp_apply (f, args) ->
4,035✔
647
        ctx.matched <- ctx.matched + 1;
648
        let ans = k |> f0 ctx loc f |> args0 ctx loc args in
75✔
649
        (* let _ = log "texp_apply + %a\n%!" MyPrinttyped.expr x in *)
650
        ans
45✔
651
      | _ -> fail loc "texp_apply")
24,666✔
652
;;
653

654
let texp_apply_nolabelled (T f0) (T args0) =
655
  let exception EarlyExit in
1,629✔
656
  let module M = struct
657
    [%%if ocaml_version < (5, 4, 0)]
658

659
    let extractor = function
660
      | Asttypes.Labelled _, _ | Asttypes.Optional _, _ | _, None -> raise EarlyExit
×
661
      | _, Some x -> x
216✔
662
    ;;
663

664
    [%%else]
665

666
    let extractor = function
667
      | Asttypes.Labelled _, _ | Asttypes.Optional _, _ | _, Omitted _ -> raise EarlyExit
668
      | _, Arg x -> x
669
    ;;
670

671
    [%%endif]
672
  end
673
  in
674
  T
675
    (fun ctx loc x k ->
676
      match x.exp_desc with
3,450✔
677
      | Texp_apply (f, args) ->
540✔
678
        ctx.matched <- ctx.matched + 1;
679
        let k = f0 ctx loc f k in
680
        (try
103✔
681
           let args = ListLabels.map args ~f:M.extractor in
682
           args0 ctx loc args k
27✔
683
         with
684
         | EarlyExit -> fail loc "texp_apply: None among the arguments")
2✔
685
      | _ -> fail loc "texp_apply")
2,910✔
686
;;
687

688
[%%if ocaml_version < (5, 4, 0)]
689

690
type constructor_description = Types.constructor_description
691
type label_description = Types.label_description
692

693
let label_name l = l.Types.lbl_name
17✔
694

695
type ('a, 'b) arg_or_omitted = 'a option
696
type apply_arg = (expression, unit) arg_or_omitted
697

698
let option_of_apply_arg = Fun.id
699

700
let arg (T fe) : (apply_arg, _, _) t =
701
  T
8,857✔
702
    (fun ctx loc x k ->
703
      match x with
100✔
704
      | Some a ->
100✔
705
        ctx.matched <- ctx.matched + 1;
706
        k |> fe ctx loc a
707
      | None -> fail loc (sprintf "arg"))
×
708
;;
709

710
[%%endif]
711
[%%if ocaml_version >= (5, 5, 0)]
712

713
type constructor_description = Data_types.constructor_description
714
type label_description = Data_types.label_description
715

716
let label_name l = l.Data_types.lbl_name
717

718
type ('a, 'b) arg_or_omitted = ('a, 'b) Typedtree.arg_or_omitted =
719
  | Arg of 'a
720
  | Omitted of 'b
721
[@@ocaml.warning "-unused-type-declaration"]
722

723
type apply_arg = (expression, unit) arg_or_omitted
724
[@@ocaml.warning "-unused-type-declaration"]
725

726
let option_of_apply_arg = function
727
  | Arg x -> Some x
728
  | Omitted _ -> None
729
;;
730

731
let arg (T fe) : (apply_arg, _, _) t =
732
  T
733
    (fun ctx loc x k ->
734
      match x with
735
      | Arg a ->
736
        ctx.matched <- ctx.matched + 1;
737
        k |> fe ctx loc a
738
      | _ -> fail loc (sprintf "arg"))
739
;;
740

741
[%%endif]
742

743
let texp_construct (T fpath) (T fcd) (T fargs) =
744
  T
250✔
745
    (fun ctx loc x k ->
746
      match x.exp_desc with
1,665✔
747
      | Texp_construct (path, cd, args) ->
246✔
748
        ctx.matched <- ctx.matched + 1;
749
        let k = fpath ctx loc path.txt k in
750
        k |> fcd ctx loc cd |> fargs ctx loc args
37✔
751
      | _ -> fail loc (sprintf "texp_construct"))
1,419✔
752
;;
753

754
let texp_assert_false () = texp_assert (texp_construct (lident (string "false")) drop nil)
63✔
755

756
let texp_let (T fvbs) (T fexpr) =
757
  T
1,650✔
758
    (fun ctx loc x k ->
759
      match x.exp_desc with
1,434✔
760
      | Texp_let (_flg, vbs, expr) ->
19✔
761
        ctx.matched <- ctx.matched + 1;
762
        k |> fvbs ctx loc vbs |> fexpr ctx loc expr
16✔
763
      | _ -> fail loc (sprintf "texp_let"))
1,415✔
764
;;
765

766
let nolabel =
767
  T
768
    (fun ctx loc x k ->
769
      match x with
268✔
770
      | Asttypes.Nolabel ->
249✔
771
        ctx.matched <- ctx.matched + 1;
772
        k
773
      | _ -> fail loc "nolabel")
19✔
774
;;
775

776
let labelled (T fstr) =
777
  T
64✔
778
    (fun ctx loc x k ->
779
      match x with
3✔
780
      | Asttypes.Labelled s ->
2✔
781
        ctx.matched <- ctx.matched + 1;
782
        k |> fstr ctx loc s
783
      | _ -> fail loc "labelled")
1✔
784
;;
785

786
let texp_apply1 f x = texp_apply f ((nolabel ** arg x) ^:: nil)
3,794✔
787
let texp_apply2 f x y = texp_apply f ((nolabel ** arg x) ^:: (nolabel ** arg y) ^:: nil)
2,405✔
788

789
[%%if ocaml_version < (4, 11, 2)]
790

791
(* 4.10 *)
792
type case_val = Typedtree.case
793
type case_comp = Typedtree.case
794
type value_pat = pattern
795
type comp_pat = pattern
796

797
[%%else]
798

799
type case_val = value case
800
type case_comp = computation case
801
type value_pat = value pattern_desc pattern_data
802
type comp_pat = computation pattern_desc pattern_data
803

804
[%%endif]
805
[%%if ocaml_version < (5, 0, 0)]
806

807
let texp_function (T fcases) =
808
  T
×
809
    (fun ctx loc e k ->
810
      match e.exp_desc with
×
811
      | Texp_function { cases } ->
×
812
        ctx.matched <- ctx.matched + 1;
813
        k |> fcases ctx loc cases
814
      | _ -> fail loc "texp_function")
×
815
;;
816

817
let texp_function_body (T fargs) (T frhs) =
818
  let rec helper acc ctx loc e k =
7,470✔
819
    match e.exp_desc with
6,841✔
820
    | Texp_function
1,019✔
821
        { cases =
822
            [ { c_lhs = { pat_desc = Tpat_var (pid, _); pat_loc; _ }
823
              ; c_rhs
824
              ; c_guard = None
825
              }
826
            ]
827
        ; arg_label
828
        ; partial = Total
829
        } -> helper ((arg_label, (pid, pat_loc)) :: acc) ctx loc c_rhs k
830
    | _ when [] = acc -> fail loc "texp_function_body"
5,076✔
831
    | _ -> k |> fargs ctx loc (List.rev acc) |> frhs ctx loc e
645✔
832
  in
833
  T (helper [])
7,470✔
834
;;
835

836
let texp_function_cases
837
  :  ((Asttypes.arg_label * (Ident.t * Location.t)) list, 'a, 'b) t
838
  -> (value case list, 'b, 'c) t
839
  -> (expression, 'a, 'c) t
840
  =
841
  fun (T fargs) (T frhs) ->
842
  let rec helper acc ctx loc e k =
6,468✔
843
    match e.exp_desc with
5,242✔
844
    | Typedtree.Texp_function
618✔
845
        { cases =
846
            [ { c_lhs = { pat_desc = Tpat_var (pid, tag); _ }; c_rhs; c_guard = _ } ]
847
        ; arg_label
848
        ; partial = Total
849
        } -> helper ((arg_label, (pid, tag.loc)) :: acc) ctx loc c_rhs k
850
    | Texp_function { cases = _ :: _ :: _ as cases; _ } ->
106✔
851
      k |> fargs ctx loc (List.rev acc) |> frhs ctx loc cases
68✔
852
    | _ -> fail loc "texp_function_cases"
4,518✔
853
  in
854
  T (helper [])
6,468✔
855
;;
856

857
[%%else]
858

859
let texp_function_cases (T fparam) (T fcases) =
860
  T
861
    (fun ctx loc e k ->
862
      match e.exp_desc with
863
      | Texp_function (params, Tfunction_cases cases) ->
864
        ctx.matched <- ctx.matched + 1;
865
        k
866
        |> fparam
867
             ctx
868
             loc
869
             (List.map (fun p -> p.Typedtree.fp_arg_label, (p.fp_param, p.fp_loc)) params)
870
        |> fcases ctx loc cases.cases
871
      | _ -> fail loc "texp_function")
872
;;
873

874
let texp_function_body (T fparam) (T fcases) =
875
  T
876
    (fun ctx loc e k ->
877
      match e.exp_desc with
878
      | Typedtree.Texp_function (params, Tfunction_body e) ->
879
        ctx.matched <- ctx.matched + 1;
880
        k
881
        |> fparam
882
             ctx
883
             loc
884
             (List.map (fun p -> p.fp_arg_label, (p.fp_param, p.fp_loc)) params)
885
        |> fcases ctx loc e
886
      | _ -> fail loc "texp_function")
887
;;
888

889
[%%endif]
890

891
let case (T pat) (T guard) (T rhs) =
892
  T
7,838✔
893
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
894
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
57✔
895
;;
896

897
let ccase (T pat) (T guard) (T rhs) =
898
  T
×
899
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
900
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
×
901
;;
902

903
[%%if ocaml_version < (5, 0, 0)]
904

905
let texp_match (T fexpr) (T fcomp_cases) (T fval_cases) =
906
  let rec split (type _a) (comps, vals) (cases : _ case list) =
3,022✔
907
    let _ : case_comp list = comps in
215✔
908
    let _ : case_val list = vals in
909
    let wrap (type a) comps vals : a case -> case_comp list * case_val list =
910
      let _ : case_comp list = comps in
147✔
911
      let _ : case_val list = vals in
912
      fun case ->
913
        match case with
147✔
914
        | { c_lhs = { pat_desc = Tpat_value p }; _ } ->
142✔
915
          ( comps
916
          , { c_lhs = (p :> pattern); c_rhs = case.c_rhs; c_guard = case.c_guard } :: vals
917
          )
918
        | { c_lhs = { pat_desc = Tpat_any }; _ } -> comps, (case :> case_val) :: vals
×
919
        | { c_lhs = { pat_desc = Tpat_var _ }; _ } -> comps, (case :> case_val) :: vals
×
920
        | { c_lhs = { pat_desc = Tpat_alias _ }; _ } -> comps, (case :> case_val) :: vals
×
921
        | { c_lhs = { pat_desc = Tpat_constant _ }; _ } ->
×
922
          comps, (case :> case_val) :: vals
923
        | { c_lhs = { pat_desc = Tpat_construct _ }; _ } ->
×
924
          comps, (case :> case_val) :: vals
925
        | { c_lhs = { pat_desc = Tpat_variant _ }; _ } ->
×
926
          comps, (case :> case_val) :: vals
927
        | { c_lhs = { pat_desc = Tpat_record _ }; _ } -> comps, (case :> case_val) :: vals
×
928
        | { c_lhs = { pat_desc = Tpat_array _ }; _ } -> comps, (case :> case_val) :: vals
×
929
        | { c_lhs = { pat_desc = Tpat_lazy _ }; _ } -> comps, (case :> case_val) :: vals
×
930
        (* | { c_lhs = { pat_desc = Tpat_value _ }; _ } -> (case :> case_comp) :: comps, vals *)
931
        | { c_lhs = { pat_desc = Tpat_exception _ }; _ } ->
3✔
932
          (case :> case_comp) :: comps, vals
933
        | { c_lhs = { pat_desc = Tpat_or _ }; _ } ->
2✔
934
          (* TODO(Kakadu): What to do here? We need to look deeply into or-pattern to understand where to place it?
935
            See issue #76
936
          *)
937
          (* failwith "Or-patterns are not yet implemented" *)
938
          comps, vals
939
        | { c_lhs; _ } ->
×
940
          (* Format.eprintf "%a\n%!" My_printtyped.pattern c_lhs; *)
941
          Format.eprintf
942
            "Unsupported pattern: tag = %d, is_block = %b\n"
943
            Obj.(tag @@ repr c_lhs)
×
944
            Obj.(is_block @@ repr c_lhs);
×
945
          assert false
×
946
    in
947
    match cases with
948
    | h :: tl -> split (wrap comps vals h) tl
147✔
949
    | [] -> List.rev comps, List.rev vals
68✔
950
  in
951
  T
952
    (fun ctx loc e k ->
953
      match e.exp_desc with
3,214✔
954
      | Texp_match (e, cases, _) ->
68✔
955
        ctx.matched <- ctx.matched + 1;
956
        let comp_cases, val_cases = split ([], []) cases in
957
        (* log
958
           "There are %d comp cases and %d val cases"
959
           (List.length comp_cases)
960
           (List.length val_cases); *)
961
        k
68✔
962
        |> fexpr ctx loc e
963
        |> fcomp_cases ctx loc comp_cases
62✔
964
        |> fval_cases ctx loc val_cases
62✔
965
      | _ -> fail loc "texp_match")
3,146✔
966
;;
967

968
[%%else]
969

970
let texp_match (T fexpr) (T fcomp_cases) (T fval_cases) =
971
  T
972
    (fun ctx loc e k ->
973
      match e.Typedtree.exp_desc with
974
      | Texp_match (e, ccases, vcases, _) ->
975
        let ccases, vcases =
976
          List.fold_left
977
            (fun (cacc, vacc) c ->
978
              match c.c_lhs.pat_desc with
979
              | Tpat_value v ->
980
                cacc, { c with c_lhs = (v :> value general_pattern) } :: vacc
981
              | _ -> cacc, vacc)
982
            ([], vcases)
983
            ccases
984
        in
985
        ctx.matched <- ctx.matched + 1;
986
        k |> fexpr ctx loc e |> fcomp_cases ctx loc ccases |> fval_cases ctx loc vcases
987
      | _ -> fail loc "texp_match")
988
;;
989

990
[%%endif]
991

992
let texp_ite (T pred) (T fthen) (T felse) =
993
  T
756✔
994
    (fun ctx loc e k ->
995
      match e.exp_desc with
8,642✔
996
      | Texp_ifthenelse (p, thenb, elseb) ->
185✔
997
        ctx.matched <- ctx.matched + 1;
998
        k |> pred ctx loc p |> fthen ctx loc thenb |> felse ctx loc elseb
77✔
999
      | _ -> fail loc "texp_ite")
8,457✔
1000
;;
1001

1002
[%%if ocaml_version < (5, 0, 0)]
1003

1004
let texp_try (T fexpr) (T fcases) =
1005
  T
63✔
1006
    (fun ctx loc e k ->
1007
      match e.exp_desc with
1,639✔
1008
      | Texp_try (e, cases) ->
3✔
1009
        ctx.matched <- ctx.matched + 1;
1010
        k |> fexpr ctx loc e |> fcases ctx loc cases
3✔
1011
      | _ -> fail loc "texp_try")
1,636✔
1012
;;
1013

1014
[%%else]
1015

1016
let texp_try (T fexpr) (T fcases) =
1017
  T
1018
    (fun ctx loc e k ->
1019
      match e.exp_desc with
1020
      | Typedtree.Texp_try (e, cases, _) ->
1021
        (* TODO: support effects *)
1022
        ctx.matched <- ctx.matched + 1;
1023
        k |> fexpr ctx loc e |> fcases ctx loc cases
1024
      | _ -> fail loc "texp_try")
1025
;;
1026

1027
[%%endif]
1028

1029
let texp_record (T fext) (T ffields) =
1030
  T
1,647✔
1031
    (fun ctx loc e k ->
1032
      match e.exp_desc with
1,647✔
1033
      | Texp_record { fields; extended_expression; _ } ->
19✔
1034
        ctx.matched <- ctx.matched + 1;
1035
        k |> fext ctx loc extended_expression |> ffields ctx loc fields
19✔
1036
      | _ -> fail loc "texp_record")
1,628✔
1037
;;
1038

1039
let texp_field (T fexpr) (T fdesc) =
1040
  T
56✔
1041
    (fun ctx loc e k ->
1042
      match e.exp_desc with
51✔
1043
      | Texp_field (e, _, desc) ->
17✔
1044
        ctx.matched <- ctx.matched + 1;
1045
        k |> fexpr ctx loc e |> fdesc ctx loc desc
17✔
1046
      | _ -> fail loc "texp_field")
34✔
1047
;;
1048

1049
[%%if ocaml_version < (5, 4, 0)]
1050

1051
let label_desc (T fname) =
1052
  T
112✔
1053
    (fun ctx loc e k ->
1054
      match e with
95✔
1055
      | { Types.lbl_name; _ } ->
95✔
1056
        ctx.matched <- ctx.matched + 1;
1057
        k |> fname ctx loc lbl_name)
1058
;;
1059

1060
[%%else]
1061

1062
let label_desc (T fname) =
1063
  T
1064
    (fun ctx loc e k ->
1065
      match e with
1066
      | { Data_types.lbl_name; _ } ->
1067
        ctx.matched <- ctx.matched + 1;
1068
        k |> fname ctx loc lbl_name)
1069
;;
1070

1071
[%%endif]
1072

1073
let rld_kept =
1074
  T
1075
    (fun ctx loc e k ->
1076
      match e with
56✔
1077
      | Kept _ ->
×
1078
        ctx.matched <- ctx.matched + 1;
1079
        k
1080
      | _ -> fail loc "rld_kept")
56✔
1081
;;
1082

1083
let rld_overriden (T flident) (T fexpr) =
1084
  T
112✔
1085
    (fun ctx loc e k ->
1086
      match e with
95✔
1087
      | Overridden ({ txt = lident }, e) ->
95✔
1088
        ctx.matched <- ctx.matched + 1;
1089
        k |> flident ctx loc lident |> fexpr ctx loc e
85✔
1090
      | _ -> fail loc "rld_overriden")
×
1091
;;
1092

1093
let value_binding (T fpat) (T fexpr) =
1094
  T
1,836✔
1095
    (fun ctx loc { vb_pat; vb_expr } k ->
1096
      ctx.matched <- ctx.matched + 1;
196✔
1097
      k |> fpat ctx loc vb_pat |> fexpr ctx loc vb_expr)
194✔
1098
;;
1099

1100
let rec core_typ (T ftexpr) = T (fun ctx loc x k -> ftexpr ctx loc x.ctyp_type k)
187✔
1101

1102
let rec typ_constr (T fpath) (T fargs) =
1103
  let rec helper ctx loc x k =
746✔
1104
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
1105
    match Types.get_desc x with
2,705✔
1106
    | Tconstr (path, args, _) ->
1,447✔
1107
      ctx.matched <- ctx.matched + 1;
1108
      k |> fpath ctx loc path |> fargs ctx loc args
236✔
1109
    | Tpoly (arg, []) | Tlink arg -> helper ctx loc arg k
×
1110
    | _ ->
1,179✔
1111
      (* let msg = Format.asprintf "typ_constr: %a " Printtyp.type_expr x in *)
1112
      fail loc "typ_constr"
1113
  in
1114
  T helper
1115
;;
1116

1117
let rec typ_arrow (T l) (T r) =
1118
  let rec helper ctx loc x k =
382✔
1119
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
1120
    match Types.get_desc x with
24✔
1121
    | Tarrow (_, tl, tr, _) ->
24✔
1122
      ctx.matched <- ctx.matched + 1;
1123
      k |> l ctx loc tl |> r ctx loc tr
24✔
1124
    | _ -> fail loc "typ_arrow"
×
1125
  in
1126
  T helper
1127
;;
1128

1129
let typ_kind_abstract =
1130
  T
1131
    (fun ctx loc x k ->
1132
      match x with
69✔
1133
      | Typedtree.Ttype_abstract ->
9✔
1134
        ctx.matched <- ctx.matched + 1;
1135
        k
1136
      | _ -> fail loc "typ_kind_abstract")
60✔
1137
;;
1138

1139
let typ_kind_open =
1140
  T
1141
    (fun ctx loc x k ->
1142
      match x with
69✔
1143
      | Typedtree.Ttype_open ->
×
1144
        ctx.matched <- ctx.matched + 1;
1145
        k
1146
      | _ -> fail loc "typ_kind_open")
69✔
1147
;;
1148

1149
let typ_kind_variant =
1150
  T
1151
    (fun ctx loc x k ->
1152
      match x with
60✔
1153
      | Typedtree.Ttype_variant _ ->
49✔
1154
        ctx.matched <- ctx.matched + 1;
1155
        k
1156
      | _ -> fail loc "typ_kind_variant")
11✔
1157
;;
1158

1159
let typ_kind_record (T flabels) =
1160
  T
61✔
1161
    (fun ctx loc x k ->
1162
      match x with
11✔
1163
      | Typedtree.Ttype_record labels ->
11✔
1164
        ctx.matched <- ctx.matched + 1;
1165
        k |> flabels ctx loc labels
1166
      | _ -> fail loc "typ_kind_record")
×
1167
;;
1168

1169
(* Structure *)
1170

1171
let tstr_attribute (T fattr) =
1172
  T
414✔
1173
    (fun ctx loc str k ->
1174
      match str.str_desc with
687✔
1175
      | Tstr_attribute attr ->
104✔
1176
        ctx.matched <- ctx.matched + 1;
1177
        k |> fattr ctx loc attr
1178
      | _ -> fail loc "tstr_attribute")
583✔
1179
;;
1180

1181
let tsig_attribute (T fattr) =
1182
  T
3✔
1183
    (fun ctx loc str k ->
1184
      match str.sig_desc with
3✔
1185
      | Tsig_attribute attr ->
2✔
1186
        ctx.matched <- ctx.matched + 1;
1187
        k |> fattr ctx loc attr
1188
      | _ -> fail loc "tsig_attribute")
1✔
1189
;;
1190

1191
let tsig_val_name (T fname) =
1192
  T
×
1193
    (fun ctx loc str k ->
1194
      match str.sig_desc with
×
1195
      | Tsig_value { val_id = txt } ->
×
1196
        ctx.matched <- ctx.matched + 1;
1197
        k |> fname ctx loc txt
1198
      | _ -> fail loc "tsig_val_name")
×
1199
;;
1200

1201
let attribute (T fname) (T fpayload) =
1202
  T
417✔
1203
    (fun ctx loc attr k ->
1204
      let open Parsetree in
106✔
1205
      k |> fname ctx loc attr.attr_name.txt |> fpayload ctx loc attr.attr_payload)
33✔
1206
;;
1207

1208
let payload_stru (T fstru) =
1209
  T
367✔
1210
    (fun ctx loc x k ->
1211
      match x with
22✔
1212
      | Parsetree.PStr stru -> k |> fstru ctx loc stru
22✔
1213
      | _ -> fail loc "payload_stru")
×
1214
;;
1215

1216
let pstr_eval (T f) =
1217
  T
324✔
1218
    (fun ctx loc x k ->
1219
      match x.Parsetree.pstr_desc with
5✔
1220
      | Parsetree.Pstr_eval (e, _) -> k |> f ctx loc e
5✔
1221
      | _ -> fail loc "pstr_eval")
×
1222
;;
1223

1224
let pexp_constant (T f) =
1225
  T
417✔
1226
    (fun ctx loc e k ->
1227
      match e.Parsetree.pexp_desc with
33✔
1228
      | Parsetree.Pexp_constant e -> k |> f ctx loc e
29✔
1229
      | _ -> fail loc "pexp_constant")
4✔
1230
;;
1231

1232
[%%if ocaml_version < (5, 0, 0)]
1233

1234
let pexp_function_cases (T fargs) (T fcases) =
1235
  let open Parsetree in
3✔
1236
  let rec helper acc ctx loc x k =
1237
    match x.pexp_desc with
9✔
1238
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
6✔
1239
    | Pexp_function cases -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc cases
3✔
1240
    | _ -> fail loc "pexp_function_cases"
×
1241
  in
1242
  T (helper [])
3✔
1243
;;
1244

1245
let pexp_function_body (T fargs) (T fcases) =
1246
  let open Parsetree in
1✔
1247
  let rec helper acc ctx loc x k =
1248
    match x.pexp_desc with
3✔
1249
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
2✔
1250
    | _ -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc x
1✔
1251
  in
1252
  T (helper [])
1✔
1253
;;
1254

1255
let pconst_string (T fstring) =
1256
  T
417✔
1257
    (fun ctx loc x k ->
1258
      match x with
29✔
1259
      | Parsetree.Pconst_string (s, _, _) -> k |> fstring ctx loc s
29✔
1260
      | _ -> fail loc "pconst_string")
×
1261
;;
1262

1263
[%%else]
1264

1265
let pexp_function_body (T fargs) (T fbody) =
1266
  let open Parsetree in
1267
  T
1268
    (fun ctx loc x k ->
1269
      match x.pexp_desc with
1270
      | Pexp_function (params, _, Pfunction_body e) ->
1271
        let args =
1272
          List.map
1273
            (fun p ->
1274
              match p.pparam_desc with
1275
              | Pparam_val (Nolabel, _, pat) -> pat
1276
              | Pparam_newtype _ | _ -> fail loc "pexp_function_body: params")
1277
            params
1278
        in
1279
        k |> fargs ctx loc args |> fbody ctx loc e
1280
      | _ -> fail loc "pexp_function_body")
1281
;;
1282

1283
let pexp_function_cases (T fargs) (T fcases) =
1284
  let open Parsetree in
1285
  T
1286
    (fun ctx loc x k ->
1287
      match x.pexp_desc with
1288
      | Pexp_function (params, _, Pfunction_cases (cases, _, _)) ->
1289
        let args =
1290
          List.map
1291
            (fun p ->
1292
              match p.pparam_desc with
1293
              | Pparam_val (Nolabel, _, pat) -> pat
1294
              | Pparam_newtype _ | _ -> fail loc "pexp_function_cases: params")
1295
            params
1296
        in
1297
        k |> fargs ctx loc args |> fcases ctx loc cases
1298
      | _ -> fail loc "pexp_function_cases")
1299
;;
1300

1301
let pconst_string (T fstring) =
1302
  T
1303
    (fun ctx loc x k ->
1304
      match x.Parsetree.pconst_desc with
1305
      | Parsetree.Pconst_string (s, _, _) -> k |> fstring ctx loc s
1306
      | _ -> fail loc "pconst_string")
1307
;;
1308

1309
[%%endif]
1310

1311
let payload_str (T fstru) =
1312
  let open Parsetree in
50✔
1313
  T
1314
    (fun ctx loc x k ->
1315
      match x with
11✔
1316
      | PStr stru -> fstru ctx loc stru k
11✔
UNCOV
1317
      | _ -> fail loc "payload_str")
×
1318
;;
1319

1320
let pexp_apply (T f) (T fargs) =
1321
  let open Parsetree in
1✔
1322
  let helper ctx loc x k =
1323
    match x.pexp_desc with
1✔
1324
    | Pexp_apply (efun, eargs) -> k |> f ctx loc efun |> fargs ctx loc eargs
1✔
UNCOV
1325
    | _ -> fail loc "pexp_apply"
×
1326
  in
1327
  T helper
1328
;;
1329

1330
let tstr_zanuda_attr str =
1331
  tstr_attribute
324✔
1332
    (attribute
324✔
1333
       (string "zanuda")
324✔
1334
       (payload_stru (pstr_eval (pexp_constant (pconst_string str)) ^:: nil)))
324✔
1335
;;
1336

1337
let pstr_eval (T f) =
1338
  let open Parsetree in
93✔
1339
  T
1340
    (fun ctx loc x k ->
1341
      match x.pstr_desc with
28✔
1342
      | Pstr_eval (e, _attrs) -> k |> f ctx loc e
28✔
UNCOV
1343
      | _ -> fail loc "pstr_eval")
×
1344
;;
1345

1346
let tstr_docattr on_str =
1347
  tstr_attribute
40✔
1348
    (attribute
40✔
1349
       drop
1350
       (payload_stru (pstr_eval (pexp_constant (pconst_string on_str)) ^:: nil)))
40✔
1351
;;
1352

1353
let tsig_docattr on_str =
1354
  tsig_attribute
3✔
1355
    (attribute
3✔
1356
       drop
1357
       (payload_stru (pstr_eval (pexp_constant (pconst_string on_str)) ^:: nil)))
3✔
1358
;;
1359

1360
type context = Ast_pattern0.context
1361

UNCOV
1362
let of_func f = T f
×
UNCOV
1363
let to_func (T f) = f
×
1364
let fail = fail
1365

1366
let%test_module "Fake tests, only to increase coverage" =
1367
  (module struct
1368
    [@@@coverage off]
1369

1370
    let noloc =
1371
      Warnings.
1372
        { loc_start = Lexing.dummy_pos; loc_end = Lexing.dummy_pos; loc_ghost = true }
1373
    ;;
1374

1375
    let%test _ =
1376
      match path_of_list [] with
1377
      | exception Failure _ -> true
1378
      | _ -> false
1379
    ;;
1380

1381
    let%test_unit _ =
1382
      let mk p ?(inv = false) what =
1383
        let on_error, rez =
1384
          if inv then Fun.const true, false else Fun.const false, true
1385
        in
1386
        parse p noloc ~on_error what rez
1387
      in
1388
      [%test_eq: Base.bool]
1389
        true
1390
        (mk
1391
           ~inv:true
1392
           (path_pident drop)
1393
           Path.(Pdot (Pident (Ident.create_local "List"), "map")));
1394
      [%test_eq: Base.bool]
1395
        true
1396
        (mk (path_pident drop) Path.(Pident (Ident.create_local "compare")));
1397
      [%test_eq: Base.bool] true (mk ~inv:true (labelled drop) Asttypes.Nolabel);
1398
      [%test_eq: Base.bool]
1399
        true
1400
        (mk
1401
           (econst drop)
1402
           { Typedtree.exp_desc = Texp_constant (Asttypes.Const_string ("", noloc, None))
1403
           ; exp_extra = []
1404
           ; exp_type = Predef.type_string
1405
           ; exp_loc = noloc
1406
           ; exp_env = Env.empty
1407
           ; exp_attributes = []
1408
           });
1409
      let _42 =
1410
        { Typedtree.exp_desc = Texp_constant (Asttypes.Const_int 42)
1411
        ; exp_extra = []
1412
        ; exp_type = Predef.type_int
1413
        ; exp_loc = noloc
1414
        ; exp_env = Env.empty
1415
        ; exp_attributes = []
1416
        }
1417
      in
1418
      [%test_eq: Base.bool] true (mk (econst drop) _42)
1419
    ;;
1420
  end)
1421
;;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc