Source file ppxlib_optcomp.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
open Ppxlib

let keep attrs =
  match List.find_map (fun a -> if a.attr_name.txt = "if" then Some a.attr_payload else None) attrs with
  | Some PStr [ {pstr_desc=Pstr_eval ({
    pexp_desc=Pexp_apply ({
      pexp_desc=Pexp_ident {txt=Lident cmp; _}; _}, [
        Nolabel, {pexp_desc=Pexp_ident {txt=Lident "ast_version"; _}; _};
        Nolabel, {pexp_desc=Pexp_constant Pconst_integer (v, None); _}
      ]); _}, _); _} ] ->
    let f = match cmp with
      | "=" -> (=) | ">" -> (>) | ">=" -> (>=) | "<" -> (<) | "<=" -> (<=)
      | "<>" -> (<>) | _ -> (fun _ _ -> true) in
    f Selected_ast.version (int_of_string v)
  | _ -> true

let rec filter_pattern = function
  | { ppat_desc = Ppat_or (p1, p2); _ } as p ->
    (match filter_pattern p1, filter_pattern p2 with
     | None, None -> None
     | Some p1, None -> Some p1
     | None, Some p2 -> Some p2
     | Some p1, Some p2 -> Some { p with ppat_desc = Ppat_or (p1, p2) })
  | { ppat_attributes; _ } as p ->
    if keep ppat_attributes then Some p else None


let transform = object inherit Ast_traverse.map as super
  method! structure s =
    let s = List.filter_map (fun it -> match it.pstr_desc with
      | Pstr_value (flag, l) ->
        let l = List.filter (fun vb -> keep vb.pvb_attributes) l in
        (match l with [] -> None | _ -> Some { it with pstr_desc = Pstr_value (flag, l) })
      | _ -> Some it
    ) s in
    super#structure s

  method! cases l =
    let l = List.filter_map (fun c ->
      let p = filter_pattern c.pc_lhs in
      Option.map (fun pc_lhs -> { c with pc_lhs }) p
    ) l in
    super#cases l

  method! expression e =
    match e.pexp_desc with
    | Pexp_let (flag, l, end_) ->
      let l = List.filter (fun vb -> keep vb.pvb_attributes) l in
      let e = match l with [] -> end_ | _ -> { e with pexp_desc = Pexp_let (flag, l, end_) } in
      super#expression e
    | _ -> super#expression e
end

let () = Driver.register_transformation ~impl:transform#structure "ppxlib_optcomp"