Skip to content

Commit add1c9b

Browse files
committed
Switch ppx_regexp to ppxlib.
1 parent b3f1d2e commit add1c9b

File tree

6 files changed

+82
-97
lines changed

6 files changed

+82
-97
lines changed

dune-workspace.dev

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
(lang dune 1.11)
2-
(context (opam (switch 4.02.3)))
3-
(context (opam (switch 4.03.0)))
42
(context (opam (switch 4.04.2)))
53
(context (opam (switch 4.05.0)))
64
(context (opam (switch 4.06.1)))
75
(context (opam (switch 4.07.1)))
86
(context (opam (switch 4.08.1)))
97
(context (opam (switch 4.09.0)))
8+
(context (opam (switch 4.11.2)))
9+
(context (opam (switch 4.12.0)))
10+
(context (opam (switch 4.13.1)))

ppx_regexp.opam

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ bug-reports: "https://github.com/paurkedal/ppx_regexp/issues"
1010
depends: [
1111
"ocaml" {>= "4.02.3"}
1212
"dune" {>= "1.11"}
13-
"ocaml-migrate-parsetree" {>= "1.4.0"}
13+
"ppxlib" {>= "0.22.2"}
1414
"re" {>= "1.7.1"}
15-
"ppx_tools_versioned" {>= "5.2.3"}
1615
"qcheck" {with-test}
1716
]
1817
build: ["dune" "build" "-p" name "-j" jobs]

ppx_regexp/dune

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
(public_name ppx_regexp)
44
(kind ppx_rewriter)
55
(modules ppx_regexp regexp)
6-
(preprocess (pps ppx_tools_versioned.metaquot_409))
7-
(libraries
8-
ocaml-migrate-parsetree
9-
ppx_tools_versioned
10-
re re.perl)
6+
(preprocess (pps ppxlib.metaquot))
7+
(libraries ppxlib re re.perl)
118
(ppx_runtime_libraries re re.perl))
129

1310
(rule (copy ../common/regexp.mli regexp.mli))

ppx_regexp/ppx_regexp.ml

Lines changed: 73 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(* Copyright (C) 2017 Petter A. Urkedal <[email protected]>
1+
(* Copyright (C) 2017--2021 Petter A. Urkedal <[email protected]>
22
*
33
* This library is free software; you can redistribute it and/or modify it
44
* under the terms of the GNU Lesser General Public License as published by
@@ -14,23 +14,16 @@
1414
* along with this library. If not, see <http://www.gnu.org/licenses/>.
1515
*)
1616

17-
open Migrate_parsetree
18-
open Ast_409
19-
let ocaml_version = Versions.ocaml_409
17+
open Ppxlib
18+
open Ast_builder.Default
2019

21-
open Ast_mapper
22-
open Ast_helper
23-
open Asttypes
24-
open Longident
25-
open Parsetree
26-
open Printf
27-
28-
let error ~loc msg = raise (Location.Error (Location.error ~loc msg))
20+
let error = Location.raise_errorf
2921

3022
let warn ~loc msg e =
31-
let e_msg = Exp.constant (Const.string msg) in
32-
let structure = {pstr_desc = Pstr_eval (e_msg, []); pstr_loc = loc} in
33-
Exp.attr e (Attr.mk ~loc {txt = "ocaml.ppwarning"; loc} (PStr [structure]))
23+
let e_msg = estring ~loc msg in
24+
let name = {txt = "ocaml.ppwarning"; loc} in
25+
let payload = PStr [{pstr_desc = Pstr_eval (e_msg, []); pstr_loc = loc}] in
26+
{e with pexp_attributes = attribute ~loc ~name ~payload :: e.pexp_attributes}
3427

3528
module List = struct
3629
include List
@@ -54,11 +47,11 @@ module Regexp = struct
5447
| Repeat ({Location.txt = (i, _); _}, e) ->
5548
recurse (must_match && i > 0) e
5649
| Nongreedy e -> recurse must_match e
57-
| Capture _ -> error ~loc "Unnamed capture is not allowed for %pcre."
50+
| Capture _ -> error ~loc "Unnamed capture is not allowed for %%pcre."
5851
| Capture_as (idr, e) ->
5952
fun (nG, bs) ->
6053
recurse must_match e (nG + 1, (idr, Some nG, must_match) :: bs)
61-
| Call _ -> error ~loc "(&...) is not implemented for %pcre.")
54+
| Call _ -> error ~loc "(&...) is not implemented for %%pcre.")
6255
in
6356
(function
6457
| {Location.txt = Capture_as (idr, e); _} ->
@@ -87,11 +80,11 @@ module Regexp = struct
8780
| Repeat ({Location.txt = (i, j_opt); _}, e) ->
8881
let j_str = match j_opt with None -> "" | Some j -> string_of_int j in
8982
delimit_if (p > p_suffix)
90-
(sprintf "%s{%d,%s}" (recurse p_atom e) i j_str)
83+
(Printf.sprintf "%s{%d,%s}" (recurse p_atom e) i j_str)
9184
| Nongreedy e -> recurse p_suffix e ^ "?"
92-
| Capture _ -> error ~loc "Unnamed capture is not allowed for %pcre."
85+
| Capture _ -> error ~loc "Unnamed capture is not allowed for %%pcre."
9386
| Capture_as (_, e) -> "(" ^ recurse p_alt e ^ ")"
94-
| Call _ -> error ~loc "(&...) is not implemented for %pcre.")
87+
| Call _ -> error ~loc "(&...) is not implemented for %%pcre.")
9588
in
9689
(function
9790
| {Location.txt = Capture_as (_, e); _} ->
@@ -100,11 +93,6 @@ module Regexp = struct
10093
recurse 0 e)
10194
end
10295

103-
let dyn_bindings = ref []
104-
let clear_bindings () = dyn_bindings := []
105-
let add_binding binding = dyn_bindings := binding :: !dyn_bindings
106-
let get_bindings () = !dyn_bindings
107-
10896
let fresh_var =
10997
let c = ref 0 in
11098
fun () -> incr c; Printf.sprintf "_ppx_regexp_%d" !c
@@ -129,7 +117,8 @@ let extract_bindings ~pos s =
129117
let r = Regexp.parse_exn ~pos s in
130118
let nG, bs = Regexp.bindings r in
131119
let re_str = Regexp.to_string r in
132-
(Exp.constant (Const.string re_str), bs, nG)
120+
let loc = Location.none in
121+
(estring ~loc re_str, bs, nG)
133122

134123
let rec wrap_group_bindings ~loc rhs offG = function
135124
| [] -> rhs
@@ -138,22 +127,22 @@ let rec wrap_group_bindings ~loc rhs offG = function
138127
| None ->
139128
[%expr Re.Group.get _g 0]
140129
| Some iG ->
141-
[%expr Re.Group.get _g [%e Exp.constant (Const.int (offG + iG + 1))]]
130+
[%expr Re.Group.get _g [%e eint ~loc (offG + iG + 1)]]
142131
in
143132
let eG =
144133
if mustG then eG else
145134
[%expr try Some [%e eG] with Not_found -> None]
146135
in
147136
[%expr
148-
let [%p Pat.var varG] = [%e eG] in
137+
let [%p ppat_var ~loc varG] = [%e eG] in
149138
[%e wrap_group_bindings ~loc rhs offG bs]]
150139

151-
let transform_cases ~mapper ~loc cases =
140+
let transform_cases ~loc cases =
152141
let aux case =
153142
if case.pc_guard <> None then
154-
error ~loc "Guards are not implemented for match%pcre." else
143+
error ~loc "Guards are not implemented for match%%pcre." else
155144
(match case.pc_lhs with
156-
| { ppat_desc = Ppat_constant (Pconst_string (re_src, re_delim));
145+
| { ppat_desc = Ppat_constant (Pconst_string (re_src, _loc, re_delim));
157146
ppat_loc = {loc_start; _}; _ } ->
158147
let re_offset =
159148
(match re_delim with Some s -> String.length s + 2 | None -> 1) in
@@ -176,87 +165,86 @@ let transform_cases ~mapper ~loc cases =
176165
| {ppat_loc = loc; _} ->
177166
error ~loc "Regular expression pattern should be a string.")
178167
in
179-
let rewrite_case case = {case with pc_rhs = mapper.expr mapper case.pc_rhs} in
180168
let cases, default_rhs =
181-
(match List.rev_map rewrite_case cases with
169+
(match List.rev (*_map rewrite_case*) cases with
182170
| {pc_lhs = {ppat_desc = Ppat_any; _}; pc_rhs; pc_guard = None} :: cases ->
183171
(cases, pc_rhs)
184172
| {pc_lhs = {ppat_desc = Ppat_var var; _}; pc_rhs; pc_guard = None} ::
185173
cases ->
186-
(cases, [%expr let [%p Pat.var var] = _ppx_regexp_v in [%e pc_rhs]])
174+
let rhs =
175+
[%expr let [%p ppat_var ~loc var] = _ppx_regexp_v in [%e pc_rhs]] in
176+
(cases, rhs)
187177
| cases ->
188178
let open Lexing in
189179
let pos = loc.Location.loc_start in
190-
let e0 = Exp.constant (Const.string pos.pos_fname) in
191-
let e1 = Exp.constant (Const.int pos.pos_lnum) in
192-
let e2 = Exp.constant (Const.int (pos.pos_cnum - pos.pos_bol)) in
180+
let e0 = estring ~loc pos.pos_fname in
181+
let e1 = eint ~loc pos.pos_lnum in
182+
let e2 = eint ~loc (pos.pos_cnum - pos.pos_bol) in
193183
let e = [%expr raise (Match_failure ([%e e0], [%e e1], [%e e2]))] in
194184
(cases, warn ~loc "A universal case is recommended for %pcre." e))
195185
in
196186
let cases = List.rev_map aux cases in
197-
let res = Exp.array (List.map (fun (re, _, _, _) -> re) cases) in
187+
let res = pexp_array ~loc (List.map (fun (re, _, _, _) -> re) cases) in
198188
let comp = [%expr
199189
let a = Array.map (fun s -> Re.mark (Re.Perl.re s)) [%e res] in
200190
let marks = Array.map fst a in
201191
let re = Re.compile (Re.alt (Array.to_list (Array.map snd a))) in
202192
(re, marks)
203193
] in
204194
let var = fresh_var () in
205-
add_binding (Vb.mk (Pat.var {txt = var; loc}) comp);
206-
let e_comp = Exp.ident {txt = Lident var; loc} in
195+
let re_binding =
196+
value_binding ~loc ~pat:(ppat_var ~loc {txt = var; loc}) ~expr:comp
197+
in
198+
let e_comp = pexp_ident ~loc {txt = Lident var; loc} in
207199

208200
let rec handle_cases i offG = function
209201
| [] -> [%expr assert false]
210202
| (_, nG, bs, rhs) :: cases ->
211-
let e_i = Exp.constant (Const.int i) in
212203
[%expr
213-
if Re.Mark.test _g (snd [%e e_comp]).([%e e_i]) then
204+
if Re.Mark.test _g (snd [%e e_comp]).([%e eint ~loc i]) then
214205
[%e wrap_group_bindings ~loc rhs offG bs]
215206
else
216207
[%e handle_cases (i + 1) (offG + nG) cases]]
217208
in
218-
[%expr
219-
(match Re.exec_opt (fst [%e e_comp]) _ppx_regexp_v with
220-
| None -> [%e default_rhs]
221-
| Some _g -> [%e handle_cases 0 0 cases])]
222-
223-
let rewrite_expr mapper e_ext =
224-
(match e_ext.pexp_desc with
225-
| Pexp_extension ({txt = "pcre"; _},
226-
PStr [{pstr_desc = Pstr_eval (e, _); _}]) ->
227-
let loc = e.pexp_loc in
228-
(match e.pexp_desc with
229-
| Pexp_match (e, cases) ->
230-
[%expr
231-
let _ppx_regexp_v = [%e e] in
232-
[%e transform_cases ~mapper ~loc cases]]
233-
| Pexp_function (cases) ->
234-
[%expr
235-
fun _ppx_regexp_v ->
236-
[%e transform_cases ~mapper ~loc cases]]
237-
| _ ->
238-
error ~loc "[%pcre] only applies to match an function.")
239-
| _ -> default_mapper.expr mapper e_ext)
209+
let cases =
210+
[%expr
211+
(match Re.exec_opt (fst [%e e_comp]) _ppx_regexp_v with
212+
| None -> [%e default_rhs]
213+
| Some _g -> [%e handle_cases 0 0 cases])]
214+
in
215+
(cases, re_binding)
216+
217+
let transformation = object
218+
inherit [value_binding list] Ast_traverse.fold_map as super
219+
220+
method! expression e_ext acc =
221+
let e_ext, acc = super#expression e_ext acc in
222+
(match e_ext.pexp_desc with
223+
| Pexp_extension
224+
({txt = "pcre"; _}, PStr [{pstr_desc = Pstr_eval (e, _); _}]) ->
225+
let loc = e.pexp_loc in
226+
(match e.pexp_desc with
227+
| Pexp_match (e, cases) ->
228+
let cases, binding = transform_cases ~loc cases in
229+
([%expr let _ppx_regexp_v = [%e e] in [%e cases]], binding :: acc)
230+
| Pexp_function (cases) ->
231+
let cases, binding = transform_cases ~loc cases in
232+
([%expr fun _ppx_regexp_v -> [%e cases]], binding :: acc)
233+
| _ ->
234+
error ~loc "[%%pcre] only applies to match an function.")
235+
| _ -> (e_ext, acc))
236+
end
240237

241-
let rewrite_structure _mapper sis =
242-
let mapper = {default_mapper with expr = rewrite_expr} in
243-
let sis' = default_mapper.structure mapper sis in
244-
(match get_bindings () |> List.rev with
245-
| [] -> sis'
246-
| bindings ->
247-
clear_bindings ();
248-
let local_sis =
249-
[%str
250-
module Ppx_regexp__local = struct
251-
[%%s [{
252-
pstr_desc = Pstr_value (Nonrecursive, bindings);
253-
pstr_loc = Location.none;
254-
}]]
255-
end
256-
open Ppx_regexp__local]
257-
in
258-
local_sis @ sis')
238+
let impl str =
239+
let str, rev_bindings = transformation#structure str [] in
240+
let re_str =
241+
let loc = Location.none in
242+
[%str
243+
module Ppx_regexp__local = struct
244+
[%%i pstr_value ~loc Nonrecursive rev_bindings]
245+
end
246+
open Ppx_regexp__local]
247+
in
248+
re_str @ str
259249

260-
let () = Driver.register ~name:"ppx_regexp" ocaml_version
261-
(fun _config _cookies ->
262-
{default_mapper with structure = rewrite_structure; expr = rewrite_expr})
250+
let () = Driver.register_transformation ~impl "ppx_regexp"

tests/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
(test
44
(name test_regexp)
55
(modules regexp test_regexp)
6-
(libraries ocaml-migrate-parsetree qcheck re re.perl))
6+
(libraries ppxlib qcheck re re.perl))
77
(rule (copy ../common/regexp.mli regexp.mli))
88
(rule (copy ../common/regexp.ml regexp.ml))
99

tests/test_regexp.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(* Copyright (C) 2018 Petter A. Urkedal <[email protected]>
1+
(* Copyright (C) 2018--2021 Petter A. Urkedal <[email protected]>
22
*
33
* This library is free software; you can redistribute it and/or modify it
44
* under the terms of the GNU Lesser General Public License as published by
@@ -15,7 +15,7 @@
1515
*)
1616

1717
open Printf
18-
module Loc = Migrate_parsetree.Ast_409.Location
18+
module Loc = Location
1919
module Q = QCheck
2020

2121
let mkloc = Loc.mkloc

0 commit comments

Comments
 (0)