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

Kakadu / zanuda / 93

04 Jul 2026 12:24PM UTC coverage: 85.254% (+0.1%) from 85.105%
93

push

github

Kakadu
CHANGES

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

2301 of 2699 relevant lines covered (85.25%)

603.05 hits per line

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

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

3
(** Copyright 2021-2026, 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))
81,252✔
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
142,000✔
44
let restore_context ctx backup = ctx.matched <- backup
93,459✔
45
let incr_matched c = c.matched <- c.matched + 1
4,600✔
46

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

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

77
let pair (T f1) (T f2) =
78
  T
10,737✔
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,345✔
98
      k)
1,345✔
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,773✔
109
  T
6,773✔
110
    (fun ctx loc x k ->
111
      if equal x v
512✔
112
      then (
216✔
113
        incr_matched ctx;
114
        (* printf "cst succeeded for %s\n%!" (to_string v); *)
115
        k)
216✔
116
      else fail loc (to_string v))
296✔
117
;;
118

119
let int v = cst ~to_string:Int.to_string v
510✔
120
let char v = cst ~to_string:(Printf.sprintf "%C") v
×
121
let string v = cst ~to_string:(Printf.sprintf "%S") v
6,263✔
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%!";
485✔
152
      match x with
485✔
153
      | [] ->
382✔
154
        ctx.matched <- ctx.matched + 1;
155
        k
156
      | _ -> fail loc "[]")
103✔
157
;;
158

159
let ( ^:: ) (T f0) (T f1) =
160
  T
25,830✔
161
    (fun ctx loc x k ->
162
      match x with
755✔
163
      | x0 :: x1 ->
696✔
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
588✔
169
        (* Format.printf "trying  cons cell succeeded\n%!"; *)
170
        k
433✔
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
260✔
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,890✔
219
    (fun ctx loc x k ->
220
      let backup = save_context ctx in
48,167✔
221
      try f1 ctx loc x k with
860✔
222
      | e1 ->
47,307✔
223
        let m1 = save_context ctx in
224
        restore_context ctx backup;
47,307✔
225
        (try f2 ctx loc x k with
781✔
226
         | e2 ->
46,526✔
227
           let m2 = save_context ctx in
228
           if m1 >= m2
46,526✔
229
           then (
46,152✔
230
             restore_context ctx m1;
231
             raise e1)
46,152✔
232
           else raise e2))
374✔
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))
384✔
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)))
384✔
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 : _ Location.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
738✔
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
65✔
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,287✔
338
    let cmp_names l r =
15,717✔
339
      let ans = String.equal l r in
8,952✔
340
      (* printf "\t\tCompare names %s and %s:  %b\n%!" l r ans; *)
341
      ans
8,952✔
342
    in
343
    match x, ps with
344
    | Path.Pident id, [ id0 ] ->
127✔
345
      if cmp_names (Ident.name id) id0
127✔
346
      then (
119✔
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
166✔
351
    | Path.Papply _, _ -> fail loc "path got Papply"
×
352
    | _ -> fail loc (sprintf "path %s" (String.concat "." xs))
15,424✔
353
  in
354
  T (helper (List.rev xs))
6,287✔
355
;;
356

357
open Typedtree
358

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

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

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

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

402
[%%if ocaml_version < (5, 0, 0)]
403

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

414
let tpat_id (T fname) =
415
  T
2,238✔
416
    (fun ctx loc x k ->
417
      match x.pat_desc with
381✔
418
      | Tpat_var (id, { loc }) ->
309✔
419
        ctx.matched <- ctx.matched + 1;
420
        k |> fname ctx loc id
421
      | _ -> fail loc "tpat_var_id")
72✔
422
;;
423

424
[%%else]
425

426
let tpat_var (T fname) =
427
  T
428
    (fun (type kind) ctx loc (x : kind pattern_desc pattern_data) k ->
429
      match x.pat_desc with
430
      | Tpat_var (_, { txt }, _uid) ->
431
        ctx.matched <- ctx.matched + 1;
432
        k |> fname ctx loc txt
433
      | Tpat_value v ->
434
        (match (v :> pattern).pat_desc with
435
         | Tpat_var (_, { txt }, _uid) ->
436
           ctx.matched <- ctx.matched + 1;
437
           k |> fname ctx loc txt
438
         | _ -> fail loc "tpat_var")
439
      | _ -> fail loc "tpat_var")
440
;;
441

442
let tpat_id (T fname) =
443
  T
444
    (fun (type kind) ctx loc (x : kind pattern_desc pattern_data) k ->
445
      match x.pat_desc with
446
      | Typedtree.Tpat_value v ->
447
        (match (v :> pattern).pat_desc with
448
         | Tpat_var (id, { loc }, _uid) ->
449
           ctx.matched <- ctx.matched + 1;
450
           k |> fname ctx loc id
451
         | _ -> fail loc "tpat_id")
452
      | Tpat_var (id, { loc }, _uid) ->
453
        ctx.matched <- ctx.matched + 1;
454
        k |> fname ctx loc id
455
      | _ -> fail loc "tpat_id 2")
456
;;
457

458
[%%endif]
459

460
let tpat_constructor (T fname) (T fargs) =
461
  T
6,312✔
462
    (fun ctx loc x k ->
463
      match x.pat_desc with
93✔
464
      | Tpat_construct ({ txt }, _, args, _) ->
80✔
465
        ctx.matched <- ctx.matched + 1;
466
        k |> fname ctx loc txt |> fargs ctx loc args
70✔
467
      | _ -> fail loc "tpat_constructor")
13✔
468
;;
469

470
[%%if ocaml_version < (5, 4, 0)]
471

472
let tpat_tuple (T fargs) =
473
  T
×
474
    (fun ctx loc x k ->
475
      match x.pat_desc with
×
476
      | Tpat_tuple pats ->
×
477
        ctx.matched <- ctx.matched + 1;
478
        k |> fargs ctx loc pats
479
      | _ -> fail loc "tpat_tuple")
×
480
;;
481

482
[%%else]
483

484
let tpat_tuple (T fargs) =
485
  T
486
    (fun ctx loc x k ->
487
      match x.pat_desc with
488
      | Tpat_tuple pats ->
489
        ctx.matched <- ctx.matched + 1;
490
        k |> fargs ctx loc (List.map snd pats)
491
      | _ -> fail loc "tpat_tuple")
492
;;
493

494
[%%endif]
495

496
let tpat_value (T fpat) =
497
  T
×
498
    (fun ctx loc x k ->
499
      match x.pat_desc with
×
500
      | Tpat_value arg ->
×
501
        let inner = (arg :> value pattern_desc pattern_data) in
502
        ctx.matched <- ctx.matched + 1;
503
        k |> fpat ctx loc inner
504
      | _ -> fail loc "tpat_value")
×
505
;;
506

507
let tpat_exception (T fpat) =
508
  T
×
509
    (fun ctx loc x k ->
510
      match x.pat_desc with
×
511
      | Tpat_exception exc ->
×
512
        ctx.matched <- ctx.matched + 1;
513
        k |> fpat ctx loc exc
514
      | _ -> fail loc "tpat_exception")
×
515
;;
516

517
let tpat_any =
518
  T
519
    (fun ctx loc x k ->
520
      match x.pat_desc with
3✔
521
      | Tpat_any ->
2✔
522
        ctx.matched <- ctx.matched + 1;
523
        k
524
      | _ -> fail loc "tpat_any")
1✔
525
;;
526

527
let texp_ident (T fpath) =
528
  T
16,493✔
529
    (fun ctx loc x k ->
530
      let __ _ = log "texp_ident %a\n%!" My_printtyped.expr x in
×
531
      match x.exp_desc with
532
      | Texp_ident (path, _, _) ->
13,616✔
533
        ctx.matched <- ctx.matched + 1;
534
        let ans = fpath ctx loc path k in
535
        log "texp_ident + %a\n%!" My_printtyped.expr x;
814✔
536
        ans
814✔
537
      | _ -> fail loc "texp_ident")
3,687✔
538
;;
539

540
let texp_ident_loc (T fpath) =
541
  T
1,473✔
542
    (fun ctx loc x k ->
543
      match x.exp_desc with
15✔
544
      | Texp_ident (path, _, _) ->
10✔
545
        ctx.matched <- ctx.matched + 1;
546
        k x.exp_loc |> fpath ctx loc path
10✔
547
      | _ -> fail loc "texp_ident")
5✔
548
;;
549

550
(* TODO(Kakadu): accept and Ident, and not a string *)
551
let pident (T fstr) =
552
  T
8,589✔
553
    (fun ctx loc x k ->
554
      match x with
243✔
555
      | Path.Pident id -> fstr ctx loc (Ident.name id) k
96✔
556
      | _ -> fail loc "pident")
147✔
557
;;
558

559
let texp_ident_typ (T fpath) (T ftyp) =
560
  T
326✔
561
    (fun ctx loc x k ->
562
      (* let __ _ = Format.printf "texp_ident_typ %a\n%!" MyPrinttyped.expr x in *)
563
      match x.exp_desc with
1,905✔
564
      | Texp_ident (path, _, typ) ->
970✔
565
        ctx.matched <- ctx.matched + 1;
566
        k |> fpath ctx loc path |> ftyp ctx loc typ.Types.val_type
514✔
567
      | _ -> fail loc "texp_ident_typ")
935✔
568
;;
569

570
[%%if ocaml_version < (5, 0, 0)]
571

572
let texp_assert (T fexp) =
573
  T
65✔
574
    (fun ctx loc x k ->
575
      match x.exp_desc with
1,691✔
576
      | Texp_assert e ->
1✔
577
        ctx.matched <- ctx.matched + 1;
578
        fexp ctx loc e k
579
      | _ -> fail loc "texp_assert")
1,690✔
580
;;
581

582
[%%else]
583

584
let texp_assert (T fexp) =
585
  T
586
    (fun ctx loc x k ->
587
       match x.exp_desc with
588
       | Texp_assert (e, _) ->
589
         ctx.matched <- ctx.matched + 1;
590
         fexp ctx loc e k
591
       | _ -> fail loc "texp_assert"
592
     : context -> Warnings.loc -> expression -> 'a -> 'b)
593
;;
594

595
[%%endif]
596

597
let texp_apply (T f0) (T args0) =
598
  T
6,821✔
599
    (fun ctx loc x k ->
600
      (* let __ _ = log "texp_apply %a\n%!" MyPrinttyped.expr x in *)
601
      match x.exp_desc with
29,542✔
602
      | Texp_apply (f, args) ->
4,247✔
603
        ctx.matched <- ctx.matched + 1;
604
        let ans = k |> f0 ctx loc f |> args0 ctx loc args in
74✔
605
        (* let _ = log "texp_apply + %a\n%!" MyPrinttyped.expr x in *)
606
        ans
44✔
607
      | _ -> fail loc "texp_apply")
25,295✔
608
;;
609

610
let texp_apply_nolabelled (T f0) (T args0) =
611
  let exception EarlyExit in
1,681✔
612
  let module M = struct
613
    [%%if ocaml_version < (5, 4, 0)]
614

615
    let extractor = function
616
      | Asttypes.Labelled _, _ | Asttypes.Optional _, _ | _, None -> raise EarlyExit
×
617
      | _, Some x -> x
216✔
618
    ;;
619

620
    [%%else]
621

622
    let extractor = function
623
      | Asttypes.Labelled _, _ | Asttypes.Optional _, _ | _, Omitted _ -> raise EarlyExit
624
      | _, Arg x -> x
625
    ;;
626

627
    [%%endif]
628
  end
629
  in
630
  T
631
    (fun ctx loc x k ->
632
      match x.exp_desc with
3,558✔
633
      | Texp_apply (f, args) ->
576✔
634
        ctx.matched <- ctx.matched + 1;
635
        let k = f0 ctx loc f k in
636
        (try
103✔
637
           let args = ListLabels.map args ~f:M.extractor in
638
           args0 ctx loc args k
27✔
639
         with
640
         | EarlyExit -> fail loc "texp_apply: None among the arguments")
2✔
641
      | _ -> fail loc "texp_apply")
2,982✔
642
;;
643

644
[%%if ocaml_version < (5, 4, 0)]
645

646
type constructor_description = Types.constructor_description
647
type label_description = Types.label_description
648

649
let label_name l = l.Types.lbl_name
17✔
650

651
type ('a, 'b) arg_or_omitted = 'a option
652
type apply_arg = (expression, unit) arg_or_omitted
653

654
let option_of_apply_arg = Fun.id
655

656
let arg (T fe) : (apply_arg, _, _) t =
657
  T
9,095✔
658
    (fun ctx loc x k ->
659
      match x with
99✔
660
      | Some a ->
99✔
661
        ctx.matched <- ctx.matched + 1;
662
        k |> fe ctx loc a
663
      | None -> fail loc (sprintf "arg"))
×
664
;;
665

666
[%%endif]
667
[%%if ocaml_version >= (5, 5, 0)]
668

669
type constructor_description = Data_types.constructor_description
670
type label_description = Data_types.label_description
671

672
let label_name l = l.Data_types.lbl_name
673

674
type ('a, 'b) arg_or_omitted = ('a, 'b) Typedtree.arg_or_omitted =
675
  | Arg of 'a
676
  | Omitted of 'b
677
[@@ocaml.warning "-unused-type-declaration"]
678

679
type apply_arg = (expression, unit) arg_or_omitted
680
[@@ocaml.warning "-unused-type-declaration"]
681

682
let option_of_apply_arg = function
683
  | Arg x -> Some x
684
  | Omitted _ -> None
685
;;
686

687
let arg (T fe) : (apply_arg, _, _) t =
688
  T
689
    (fun ctx loc x k ->
690
      match x with
691
      | Arg a ->
692
        ctx.matched <- ctx.matched + 1;
693
        k |> fe ctx loc a
694
      | _ -> fail loc (sprintf "arg"))
695
;;
696

697
[%%endif]
698

699
let texp_construct (T fpath) (T fcd) (T fargs) =
700
  T
254✔
701
    (fun ctx loc x k ->
702
      match x.exp_desc with
1,711✔
703
      | Texp_construct (path, cd, args) ->
246✔
704
        ctx.matched <- ctx.matched + 1;
705
        let k = fpath ctx loc path.txt k in
706
        k |> fcd ctx loc cd |> fargs ctx loc args
37✔
707
      | _ -> fail loc (sprintf "texp_construct"))
1,465✔
708
;;
709

710
let texp_assert_false () = texp_assert (texp_construct (lident (string "false")) drop nil)
65✔
711

712
let texp_let (T fvbs) (T fexpr) =
713
  T
1,696✔
714
    (fun ctx loc x k ->
715
      match x.exp_desc with
1,479✔
716
      | Texp_let (_flg, vbs, expr) ->
19✔
717
        ctx.matched <- ctx.matched + 1;
718
        k |> fvbs ctx loc vbs |> fexpr ctx loc expr
16✔
719
      | _ -> fail loc (sprintf "texp_let"))
1,460✔
720
;;
721

722
let nolabel =
723
  T
724
    (fun ctx loc x k ->
725
      match x with
268✔
726
      | Asttypes.Nolabel ->
249✔
727
        ctx.matched <- ctx.matched + 1;
728
        k
729
      | _ -> fail loc "nolabel")
19✔
730
;;
731

732
let labelled (T fstr) =
733
  T
66✔
734
    (fun ctx loc x k ->
735
      match x with
3✔
736
      | Asttypes.Labelled s ->
2✔
737
        ctx.matched <- ctx.matched + 1;
738
        k |> fstr ctx loc s
739
      | _ -> fail loc "labelled")
1✔
740
;;
741

742
let texp_apply1 f x = texp_apply f ((nolabel ** arg x) ^:: nil)
3,896✔
743
let texp_apply2 f x y = texp_apply f ((nolabel ** arg x) ^:: (nolabel ** arg y) ^:: nil)
2,469✔
744

745
[%%if ocaml_version < (4, 11, 2)]
746

747
(* 4.10 *)
748
type case_val = Typedtree.case
749
type case_comp = Typedtree.case
750
type value_pat = pattern
751
type comp_pat = pattern
752

753
[%%else]
754

755
type case_val = value case
756
type case_comp = computation case
757
type value_pat = value pattern_desc pattern_data
758
type comp_pat = computation pattern_desc pattern_data
759

760
[%%endif]
761
[%%if ocaml_version < (5, 0, 0)]
762

763
let texp_function (T fcases) =
764
  T
×
765
    (fun ctx loc e k ->
766
      match e.exp_desc with
×
767
      | Texp_function { cases } ->
×
768
        ctx.matched <- ctx.matched + 1;
769
        k |> fcases ctx loc cases
770
      | _ -> fail loc "texp_function")
×
771
;;
772

773
let texp_function_body (T fargs) (T frhs) =
774
  let rec helper acc ctx loc e k =
7,656✔
775
    match e.exp_desc with
6,983✔
776
    | Texp_function
1,021✔
777
        { cases =
778
            [ { c_lhs = { pat_desc = Tpat_var (pid, _); pat_loc; _ }
779
              ; c_rhs
780
              ; c_guard = None
781
              }
782
            ]
783
        ; arg_label
784
        ; partial = Total
785
        } -> helper ((arg_label, (pid, pat_loc)) :: acc) ctx loc c_rhs k
786
    | _ when [] = acc -> fail loc "texp_function_body"
5,214✔
787
    | _ -> k |> fargs ctx loc (List.rev acc) |> frhs ctx loc e
647✔
788
  in
789
  T (helper [])
7,656✔
790
;;
791

792
let texp_function_cases
793
  :  ((Asttypes.arg_label * (Ident.t * Location.t)) list, 'a, 'b) t
794
  -> (value case list, 'b, 'c) t
795
  -> (expression, 'a, 'c) t
796
  =
797
  fun (T fargs) (T frhs) ->
798
  let rec helper acc ctx loc e k =
6,660✔
799
    match e.exp_desc with
5,389✔
800
    | Typedtree.Texp_function
620✔
801
        { cases =
802
            [ { c_lhs = { pat_desc = Tpat_var (pid, tag); _ }; c_rhs; c_guard = _ } ]
803
        ; arg_label
804
        ; partial = Total
805
        } -> helper ((arg_label, (pid, tag.loc)) :: acc) ctx loc c_rhs k
806
    | Texp_function { cases = _ :: _ :: _ as cases; _ } ->
106✔
807
      k |> fargs ctx loc (List.rev acc) |> frhs ctx loc cases
68✔
808
    | _ -> fail loc "texp_function_cases"
4,663✔
809
  in
810
  T (helper [])
6,660✔
811
;;
812

813
[%%else]
814

815
let texp_function_cases (T fparam) (T fcases) =
816
  T
817
    (fun ctx loc e k ->
818
      match e.exp_desc with
819
      | Texp_function (params, Tfunction_cases cases) ->
820
        ctx.matched <- ctx.matched + 1;
821
        k
822
        |> fparam
823
             ctx
824
             loc
825
             (List.map (fun p -> p.Typedtree.fp_arg_label, (p.fp_param, p.fp_loc)) params)
826
        |> fcases ctx loc cases.cases
827
      | _ -> fail loc "texp_function")
828
;;
829

830
let texp_function_body (T fparam) (T fcases) =
831
  T
832
    (fun ctx loc e k ->
833
      match e.exp_desc with
834
      | Typedtree.Texp_function (params, Tfunction_body e) ->
835
        ctx.matched <- ctx.matched + 1;
836
        k
837
        |> fparam
838
             ctx
839
             loc
840
             (List.map (fun p -> p.fp_arg_label, (p.fp_param, p.fp_loc)) params)
841
        |> fcases ctx loc e
842
      | _ -> fail loc "texp_function")
843
;;
844

845
[%%endif]
846

847
let case (T pat) (T guard) (T rhs) =
848
  T
8,070✔
849
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
850
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
57✔
851
;;
852

853
let ccase (T pat) (T guard) (T rhs) =
854
  T
×
855
    (fun ctx loc { c_lhs; c_rhs; c_guard } k ->
856
      k |> pat ctx loc c_lhs |> guard ctx loc c_guard |> rhs ctx loc c_rhs)
×
857
;;
858

859
[%%if ocaml_version < (5, 0, 0)]
860

861
let texp_match (T fexpr) (T fcomp_cases) (T fval_cases) =
862
  let rec split (type _a) (comps, vals) (cases : _ case list) =
3,116✔
863
    let _ : case_comp list = comps in
215✔
864
    let _ : case_val list = vals in
865
    let wrap (type a) comps vals : a case -> case_comp list * case_val list =
866
      let _ : case_comp list = comps in
147✔
867
      let _ : case_val list = vals in
868
      fun case ->
869
        match case with
147✔
870
        | { c_lhs = { pat_desc = Tpat_value p }; _ } ->
142✔
871
          ( comps
872
          , { c_lhs = (p :> pattern); c_rhs = case.c_rhs; c_guard = case.c_guard } :: vals
873
          )
874
        | { c_lhs = { pat_desc = Tpat_any }; _ } -> comps, (case :> case_val) :: vals
×
875
        | { c_lhs = { pat_desc = Tpat_var _ }; _ } -> comps, (case :> case_val) :: vals
×
876
        | { c_lhs = { pat_desc = Tpat_alias _ }; _ } -> comps, (case :> case_val) :: vals
×
877
        | { c_lhs = { pat_desc = Tpat_constant _ }; _ } ->
×
878
          comps, (case :> case_val) :: vals
879
        | { c_lhs = { pat_desc = Tpat_construct _ }; _ } ->
×
880
          comps, (case :> case_val) :: vals
881
        | { c_lhs = { pat_desc = Tpat_variant _ }; _ } ->
×
882
          comps, (case :> case_val) :: vals
883
        | { c_lhs = { pat_desc = Tpat_record _ }; _ } -> comps, (case :> case_val) :: vals
×
884
        | { c_lhs = { pat_desc = Tpat_array _ }; _ } -> comps, (case :> case_val) :: vals
×
885
        | { c_lhs = { pat_desc = Tpat_lazy _ }; _ } -> comps, (case :> case_val) :: vals
×
886
        (* | { c_lhs = { pat_desc = Tpat_value _ }; _ } -> (case :> case_comp) :: comps, vals *)
887
        | { c_lhs = { pat_desc = Tpat_exception _ }; _ } ->
3✔
888
          (case :> case_comp) :: comps, vals
889
        | { c_lhs = { pat_desc = Tpat_or _ }; _ } ->
2✔
890
          (* TODO(Kakadu): What to do here? We need to look deeply into or-pattern to understand where to place it?
891
            See issue #76
892
          *)
893
          (* failwith "Or-patterns are not yet implemented" *)
894
          comps, vals
895
        | { c_lhs; _ } ->
×
896
          (* Format.eprintf "%a\n%!" My_printtyped.pattern c_lhs; *)
897
          Format.eprintf
898
            "Unsupported pattern: tag = %d, is_block = %b\n"
899
            Obj.(tag @@ repr c_lhs)
×
900
            Obj.(is_block @@ repr c_lhs);
×
901
          assert false
×
902
    in
903
    match cases with
904
    | h :: tl -> split (wrap comps vals h) tl
147✔
905
    | [] -> List.rev comps, List.rev vals
68✔
906
  in
907
  T
908
    (fun ctx loc e k ->
909
      match e.exp_desc with
3,307✔
910
      | Texp_match (e, cases, _) ->
68✔
911
        ctx.matched <- ctx.matched + 1;
912
        let comp_cases, val_cases = split ([], []) cases in
913
        (* log
914
           "There are %d comp cases and %d val cases"
915
           (List.length comp_cases)
916
           (List.length val_cases); *)
917
        k
68✔
918
        |> fexpr ctx loc e
919
        |> fcomp_cases ctx loc comp_cases
62✔
920
        |> fval_cases ctx loc val_cases
62✔
921
      | _ -> fail loc "texp_match")
3,239✔
922
;;
923

924
[%%else]
925

926
let texp_match (T fexpr) (T fcomp_cases) (T fval_cases) =
927
  T
928
    (fun ctx loc e k ->
929
      match e.Typedtree.exp_desc with
930
      | Texp_match (e, ccases, vcases, _) ->
931
        let ccases, vcases =
932
          List.fold_left
933
            (fun (cacc, vacc) c ->
934
              match c.c_lhs.pat_desc with
935
              | Tpat_value v ->
936
                cacc, { c with c_lhs = (v :> value general_pattern) } :: vacc
937
              | _ -> cacc, vacc)
938
            ([], vcases)
939
            ccases
940
        in
941
        ctx.matched <- ctx.matched + 1;
942
        k |> fexpr ctx loc e |> fcomp_cases ctx loc ccases |> fval_cases ctx loc vcases
943
      | _ -> fail loc "texp_match")
944
;;
945

946
[%%endif]
947

948
let texp_ite (T pred) (T fthen) (T felse) =
949
  T
780✔
950
    (fun ctx loc e k ->
951
      match e.exp_desc with
8,950✔
952
      | Texp_ifthenelse (p, thenb, elseb) ->
185✔
953
        ctx.matched <- ctx.matched + 1;
954
        k |> pred ctx loc p |> fthen ctx loc thenb |> felse ctx loc elseb
77✔
955
      | _ -> fail loc "texp_ite")
8,765✔
956
;;
957

958
[%%if ocaml_version < (5, 0, 0)]
959

960
let texp_try (T fexpr) (T fcases) =
961
  T
65✔
962
    (fun ctx loc e k ->
963
      match e.exp_desc with
1,693✔
964
      | Texp_try (e, cases) ->
3✔
965
        ctx.matched <- ctx.matched + 1;
966
        k |> fexpr ctx loc e |> fcases ctx loc cases
3✔
967
      | _ -> fail loc "texp_try")
1,690✔
968
;;
969

970
[%%else]
971

972
let texp_try (T fexpr) (T fcases) =
973
  T
974
    (fun ctx loc e k ->
975
      match e.exp_desc with
976
      | Typedtree.Texp_try (e, cases, _) ->
977
        (* TODO: support effects *)
978
        ctx.matched <- ctx.matched + 1;
979
        k |> fexpr ctx loc e |> fcases ctx loc cases
980
      | _ -> fail loc "texp_try")
981
;;
982

983
[%%endif]
984

985
let texp_record (T fext) (T ffields) =
986
  T
1,693✔
987
    (fun ctx loc e k ->
988
      match e.exp_desc with
1,693✔
989
      | Texp_record { fields; extended_expression; _ } ->
19✔
990
        ctx.matched <- ctx.matched + 1;
991
        k |> fext ctx loc extended_expression |> ffields ctx loc fields
19✔
992
      | _ -> fail loc "texp_record")
1,674✔
993
;;
994

995
let texp_field (T fexpr) (T fdesc) =
996
  T
56✔
997
    (fun ctx loc e k ->
998
      match e.exp_desc with
51✔
999
      | Texp_field (e, _, desc) ->
17✔
1000
        ctx.matched <- ctx.matched + 1;
1001
        k |> fexpr ctx loc e |> fdesc ctx loc desc
17✔
1002
      | _ -> fail loc "texp_field")
34✔
1003
;;
1004

1005
[%%if ocaml_version < (5, 4, 0)]
1006

1007
let label_desc (T fname) =
1008
  T
112✔
1009
    (fun ctx loc e k ->
1010
      match e with
95✔
1011
      | { Types.lbl_name; _ } ->
95✔
1012
        ctx.matched <- ctx.matched + 1;
1013
        k |> fname ctx loc lbl_name)
1014
;;
1015

1016
[%%else]
1017

1018
let label_desc (T fname) =
1019
  T
1020
    (fun ctx loc e k ->
1021
      match e with
1022
      | { Data_types.lbl_name; _ } ->
1023
        ctx.matched <- ctx.matched + 1;
1024
        k |> fname ctx loc lbl_name)
1025
;;
1026

1027
[%%endif]
1028

1029
let rld_kept =
1030
  T
1031
    (fun ctx loc e k ->
1032
      match e with
56✔
1033
      | Kept _ ->
×
1034
        ctx.matched <- ctx.matched + 1;
1035
        k
1036
      | _ -> fail loc "rld_kept")
56✔
1037
;;
1038

1039
let rld_overriden (T flident) (T fexpr) =
1040
  T
112✔
1041
    (fun ctx loc e k ->
1042
      match e with
95✔
1043
      | Overridden ({ txt = lident }, e) ->
95✔
1044
        ctx.matched <- ctx.matched + 1;
1045
        k |> flident ctx loc lident |> fexpr ctx loc e
85✔
1046
      | _ -> fail loc "rld_overriden")
×
1047
;;
1048

1049
let value_binding (T fpat) (T fexpr) =
1050
  T
1,882✔
1051
    (fun ctx loc { vb_pat; vb_expr } k ->
1052
      ctx.matched <- ctx.matched + 1;
196✔
1053
      k |> fpat ctx loc vb_pat |> fexpr ctx loc vb_expr)
194✔
1054
;;
1055

1056
let rec core_typ (T ftexpr) = T (fun ctx loc x k -> ftexpr ctx loc x.ctyp_type k)
193✔
1057

1058
let rec typ_constr (T fpath) (T fargs) =
1059
  let rec helper ctx loc x k =
770✔
1060
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
1061
    match Types.get_desc x with
2,809✔
1062
    | Tconstr (path, args, _) ->
1,483✔
1063
      ctx.matched <- ctx.matched + 1;
1064
      k |> fpath ctx loc path |> fargs ctx loc args
236✔
1065
    | Tpoly (arg, []) | Tlink arg -> helper ctx loc arg k
×
1066
    | _ ->
1,247✔
1067
      (* let msg = Format.asprintf "typ_constr: %a " Printtyp.type_expr x in *)
1068
      fail loc "typ_constr"
1069
  in
1070
  T helper
1071
;;
1072

1073
let rec typ_arrow (T l) (T r) =
1074
  let rec helper ctx loc x k =
394✔
1075
    (* Format.printf "typ = %a\n%!" Printtyp.type_expr x; *)
1076
    match Types.get_desc x with
24✔
1077
    | Tarrow (_, tl, tr, _) ->
24✔
1078
      ctx.matched <- ctx.matched + 1;
1079
      k |> l ctx loc tl |> r ctx loc tr
24✔
1080
    | _ -> fail loc "typ_arrow"
×
1081
  in
1082
  T helper
1083
;;
1084

1085
let typ_kind_abstract =
1086
  T
1087
    (fun ctx loc x k ->
1088
      match x with
69✔
1089
      | Typedtree.Ttype_abstract ->
9✔
1090
        ctx.matched <- ctx.matched + 1;
1091
        k
1092
      | _ -> fail loc "typ_kind_abstract")
60✔
1093
;;
1094

1095
let typ_kind_open =
1096
  T
1097
    (fun ctx loc x k ->
1098
      match x with
69✔
1099
      | Typedtree.Ttype_open ->
×
1100
        ctx.matched <- ctx.matched + 1;
1101
        k
1102
      | _ -> fail loc "typ_kind_open")
69✔
1103
;;
1104

1105
let typ_kind_variant =
1106
  T
1107
    (fun ctx loc x k ->
1108
      match x with
60✔
1109
      | Typedtree.Ttype_variant _ ->
49✔
1110
        ctx.matched <- ctx.matched + 1;
1111
        k
1112
      | _ -> fail loc "typ_kind_variant")
11✔
1113
;;
1114

1115
let typ_kind_record (T flabels) =
1116
  T
63✔
1117
    (fun ctx loc x k ->
1118
      match x with
11✔
1119
      | Typedtree.Ttype_record labels ->
11✔
1120
        ctx.matched <- ctx.matched + 1;
1121
        k |> flabels ctx loc labels
1122
      | _ -> fail loc "typ_kind_record")
×
1123
;;
1124

1125
(* Structure *)
1126

1127
let tstr_attribute (T fattr) =
1128
  T
417✔
1129
    (fun ctx loc str k ->
1130
      match str.str_desc with
691✔
1131
      | Tstr_attribute attr ->
106✔
1132
        ctx.matched <- ctx.matched + 1;
1133
        k |> fattr ctx loc attr
1134
      | _ -> fail loc "tstr_attribute")
585✔
1135
;;
1136

1137
let tsig_attribute (T fattr) =
1138
  T
3✔
1139
    (fun ctx loc str k ->
1140
      match str.sig_desc with
3✔
1141
      | Tsig_attribute attr ->
2✔
1142
        ctx.matched <- ctx.matched + 1;
1143
        k |> fattr ctx loc attr
1144
      | _ -> fail loc "tsig_attribute")
1✔
1145
;;
1146

1147
let tsig_val_name (T fname) =
1148
  T
×
1149
    (fun ctx loc str k ->
1150
      match str.sig_desc with
×
1151
      | Tsig_value { val_id = txt } ->
×
1152
        ctx.matched <- ctx.matched + 1;
1153
        k |> fname ctx loc txt
1154
      | _ -> fail loc "tsig_val_name")
×
1155
;;
1156

1157
let attribute (T fname) (T fpayload) =
1158
  T
420✔
1159
    (fun ctx loc attr k ->
1160
      let open Parsetree in
108✔
1161
      k |> fname ctx loc attr.attr_name.txt |> fpayload ctx loc attr.attr_payload)
34✔
1162
;;
1163

1164
let payload_stru (T fstru) =
1165
  T
369✔
1166
    (fun ctx loc x k ->
1167
      match x with
23✔
1168
      | Parsetree.PStr stru -> k |> fstru ctx loc stru
23✔
1169
      | _ -> fail loc "payload_stru")
×
1170
;;
1171

1172
let pstr_eval (T f) =
1173
  T
326✔
1174
    (fun ctx loc x k ->
1175
      match x.Parsetree.pstr_desc with
6✔
1176
      | Parsetree.Pstr_eval (e, _) -> k |> f ctx loc e
6✔
1177
      | _ -> fail loc "pstr_eval")
×
1178
;;
1179

1180
let pexp_constant (T f) =
1181
  T
420✔
1182
    (fun ctx loc e k ->
1183
      match e.Parsetree.pexp_desc with
34✔
1184
      | Parsetree.Pexp_constant e -> k |> f ctx loc e
30✔
1185
      | _ -> fail loc "pexp_constant")
4✔
1186
;;
1187

1188
[%%if ocaml_version < (5, 0, 0)]
1189

1190
let pexp_function_cases (T fargs) (T fcases) =
1191
  let open Parsetree in
3✔
1192
  let rec helper acc ctx loc x k =
1193
    match x.pexp_desc with
9✔
1194
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
6✔
1195
    | Pexp_function cases -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc cases
3✔
1196
    | _ -> fail loc "pexp_function_cases"
×
1197
  in
1198
  T (helper [])
3✔
1199
;;
1200

1201
let pexp_function_body (T fargs) (T fcases) =
1202
  let open Parsetree in
1✔
1203
  let rec helper acc ctx loc x k =
1204
    match x.pexp_desc with
3✔
1205
    | Pexp_fun (Asttypes.Nolabel, None, pat, rhs) -> helper (pat :: acc) ctx loc rhs k
2✔
1206
    | _ -> k |> fargs ctx loc (List.rev acc) |> fcases ctx loc x
1✔
1207
  in
1208
  T (helper [])
1✔
1209
;;
1210

1211
let pconst_string (T fstring) =
1212
  T
420✔
1213
    (fun ctx loc x k ->
1214
      match x with
30✔
1215
      | Parsetree.Pconst_string (s, _, _) -> k |> fstring ctx loc s
30✔
1216
      | _ -> fail loc "pconst_string")
×
1217
;;
1218

1219
[%%else]
1220

1221
let pexp_function_body (T fargs) (T fbody) =
1222
  let open Parsetree in
1223
  T
1224
    (fun ctx loc x k ->
1225
      match x.pexp_desc with
1226
      | Pexp_function (params, _, Pfunction_body e) ->
1227
        let args =
1228
          List.map
1229
            (fun p ->
1230
              match p.pparam_desc with
1231
              | Pparam_val (Nolabel, _, pat) -> pat
1232
              | Pparam_newtype _ | _ -> fail loc "pexp_function_body: params")
1233
            params
1234
        in
1235
        k |> fargs ctx loc args |> fbody ctx loc e
1236
      | _ -> fail loc "pexp_function_body")
1237
;;
1238

1239
let pexp_function_cases (T fargs) (T fcases) =
1240
  let open Parsetree in
1241
  T
1242
    (fun ctx loc x k ->
1243
      match x.pexp_desc with
1244
      | Pexp_function (params, _, Pfunction_cases (cases, _, _)) ->
1245
        let args =
1246
          List.map
1247
            (fun p ->
1248
              match p.pparam_desc with
1249
              | Pparam_val (Nolabel, _, pat) -> pat
1250
              | Pparam_newtype _ | _ -> fail loc "pexp_function_cases: params")
1251
            params
1252
        in
1253
        k |> fargs ctx loc args |> fcases ctx loc cases
1254
      | _ -> fail loc "pexp_function_cases")
1255
;;
1256

1257
let pconst_string (T fstring) =
1258
  T
1259
    (fun ctx loc x k ->
1260
      match x.Parsetree.pconst_desc with
1261
      | Parsetree.Pconst_string (s, _, _) -> k |> fstring ctx loc s
1262
      | _ -> fail loc "pconst_string")
1263
;;
1264

1265
[%%endif]
1266

1267
let payload_str (T fstru) =
1268
  let open Parsetree in
51✔
1269
  T
1270
    (fun ctx loc x k ->
1271
      match x with
11✔
1272
      | PStr stru -> fstru ctx loc stru k
11✔
1273
      | _ -> fail loc "payload_str")
×
1274
;;
1275

1276
let pexp_apply (T f) (T fargs) =
1277
  let open Parsetree in
1✔
1278
  let helper ctx loc x k =
1279
    match x.pexp_desc with
1✔
1280
    | Pexp_apply (efun, eargs) -> k |> f ctx loc efun |> fargs ctx loc eargs
1✔
1281
    | _ -> fail loc "pexp_apply"
×
1282
  in
1283
  T helper
1284
;;
1285

1286
let tstr_zanuda_attr str =
1287
  tstr_attribute
326✔
1288
    (attribute
326✔
1289
       (string "zanuda")
326✔
1290
       (payload_stru (pstr_eval (pexp_constant (pconst_string str)) ^:: nil)))
326✔
1291
;;
1292

1293
let pstr_eval (T f) =
1294
  let open Parsetree in
94✔
1295
  T
1296
    (fun ctx loc x k ->
1297
      match x.pstr_desc with
28✔
1298
      | Pstr_eval (e, _attrs) -> k |> f ctx loc e
28✔
1299
      | _ -> fail loc "pstr_eval")
×
1300
;;
1301

1302
let tstr_docattr on_str =
1303
  tstr_attribute
40✔
1304
    (attribute
40✔
1305
       drop
1306
       (payload_stru (pstr_eval (pexp_constant (pconst_string on_str)) ^:: nil)))
40✔
1307
;;
1308

1309
let tsig_docattr on_str =
1310
  tsig_attribute
3✔
1311
    (attribute
3✔
1312
       drop
1313
       (payload_stru (pstr_eval (pexp_constant (pconst_string on_str)) ^:: nil)))
3✔
1314
;;
1315

1316
type context = Ast_pattern0.context
1317

1318
let of_func f = T f
×
1319
let to_func (T f) = f
×
1320
let fail = fail
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