Skip to content

Commit 1bbd890

Browse files
committed
Port quoter ident optimization from ppx_deriving
From: ocaml-ppx/ppx_deriving#252. Signed-off-by: Simmo Saan <[email protected]>
1 parent c32fb0f commit 1bbd890

File tree

2 files changed

+137
-123
lines changed

2 files changed

+137
-123
lines changed

src/quoter.ml

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,26 @@ let quote t (e : expression) =
1818
let loc = e.pexp_loc in
1919
let (module Ast) = Ast_builder.make loc in
2020
let name = "__" ^ Int.to_string t.next_id in
21+
let (binding_expr, quoted_expr) =
22+
match e with
23+
(* Optimize identifier quoting by avoiding closure.
24+
See https://github.com/ocaml-ppx/ppx_deriving/pull/252. *)
25+
| { pexp_desc = Pexp_ident _; _ } ->
26+
(e, Ast.evar name)
27+
| _ ->
28+
let binding_expr =
29+
Ast.pexp_fun Nolabel None
30+
(let unit = Ast_builder.Default.Located.lident ~loc "()" in
31+
Ast.ppat_construct unit None)
32+
e
33+
in
34+
let quoted_expr = Ast.eapply (Ast.evar name) [Ast.eunit] in
35+
(binding_expr, quoted_expr)
36+
in
2137
let binding =
2238
let pat = Ast.pvar name in
23-
let expr =
24-
Ast.pexp_fun Nolabel None
25-
(let unit = Ast_builder.Default.Located.lident ~loc "()" in
26-
Ast.ppat_construct unit None)
27-
e
28-
in
29-
Ast.value_binding ~pat ~expr
39+
Ast.value_binding ~pat ~expr:binding_expr
3040
in
3141
t.bindings <- binding :: t.bindings;
3242
t.next_id <- t.next_id + 1;
33-
Ast.eapply (Ast.evar name) [Ast.eunit]
43+
quoted_expr

test/quoter/test.ml

Lines changed: 119 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -18,49 +18,16 @@ let expr1 =
1818
[%%expect{|
1919
val expr1 : expression =
2020
{Ppxlib__.Import.pexp_desc =
21-
Ppxlib__.Import.Pexp_apply
22-
({Ppxlib__.Import.pexp_desc =
23-
Ppxlib__.Import.Pexp_ident
24-
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "__0";
25-
loc =
26-
{Ppxlib__.Import.loc_start =
27-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
28-
pos_bol = 0; pos_cnum = -1};
29-
loc_end =
30-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
31-
pos_bol = 0; pos_cnum = -1};
32-
loc_ghost = true}};
33-
pexp_loc =
34-
{Ppxlib__.Import.loc_start =
35-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
36-
pos_cnum = -1};
37-
loc_end =
38-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
39-
pos_cnum = -1};
40-
loc_ghost = true};
41-
pexp_loc_stack = []; pexp_attributes = []},
42-
[(Ppxlib__.Import.Nolabel,
43-
{Ppxlib__.Import.pexp_desc =
44-
Ppxlib__.Import.Pexp_construct
45-
({Ppxlib__.Import.txt = Ppxlib__.Import.Lident "()";
46-
loc =
47-
{Ppxlib__.Import.loc_start =
48-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
49-
pos_bol = 0; pos_cnum = -1};
50-
loc_end =
51-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
52-
pos_bol = 0; pos_cnum = -1};
53-
loc_ghost = true}},
54-
None);
55-
pexp_loc =
56-
{Ppxlib__.Import.loc_start =
57-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
58-
pos_cnum = -1};
59-
loc_end =
60-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
61-
pos_cnum = -1};
62-
loc_ghost = true};
63-
pexp_loc_stack = []; pexp_attributes = []})]);
21+
Ppxlib__.Import.Pexp_ident
22+
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "__0";
23+
loc =
24+
{Ppxlib__.Import.loc_start =
25+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
26+
pos_cnum = -1};
27+
loc_end =
28+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
29+
pos_cnum = -1};
30+
loc_ghost = true}};
6431
pexp_loc =
6532
{Ppxlib__.Import.loc_start =
6633
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
@@ -74,19 +41,46 @@ val expr1 : expression =
7441

7542
Pprintast.string_of_expression expr1;;
7643
[%%expect{|
77-
- : string = "__0 ()"
44+
- : string = "__0"
7845
|}]
7946

8047
let expr2 =
8148
Ast_builder.Default.evar ~loc:Location.none "bar"
8249
|> Quoter.quote quoter
8350
[%%expect{|
8451
val expr2 : expression =
52+
{Ppxlib__.Import.pexp_desc =
53+
Ppxlib__.Import.Pexp_ident
54+
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "__1";
55+
loc =
56+
{Ppxlib__.Import.loc_start =
57+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
58+
pos_cnum = -1};
59+
loc_end =
60+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
61+
pos_cnum = -1};
62+
loc_ghost = true}};
63+
pexp_loc =
64+
{Ppxlib__.Import.loc_start =
65+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
66+
pos_cnum = -1};
67+
loc_end =
68+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
69+
pos_cnum = -1};
70+
loc_ghost = true};
71+
pexp_loc_stack = []; pexp_attributes = []}
72+
|}]
73+
74+
let expr3 =
75+
Ast.eapply ~loc:Location.none (Ast.evar "foo" ~loc:Location.none) [Ast.eunit ~loc:Location.none]
76+
|> Quoter.quote quoter
77+
[%%expect{|
78+
val expr3 : expression =
8579
{Ppxlib__.Import.pexp_desc =
8680
Ppxlib__.Import.Pexp_apply
8781
({Ppxlib__.Import.pexp_desc =
8882
Ppxlib__.Import.Pexp_ident
89-
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "__1";
83+
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "__2";
9084
loc =
9185
{Ppxlib__.Import.loc_start =
9286
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
@@ -137,8 +131,13 @@ val expr2 : expression =
137131
pexp_loc_stack = []; pexp_attributes = []}
138132
|}]
139133

134+
Pprintast.string_of_expression expr3;;
135+
[%%expect{|
136+
- : string = "__2 ()"
137+
|}]
138+
140139
let quoted =
141-
let expr = Ast.elist ~loc:Location.none [expr1; expr2] in
140+
let expr = Ast.elist ~loc:Location.none [expr1; expr2; expr3] in
142141
Quoter.sanitize quoter expr
143142
[%%expect{|
144143
val quoted : expression =
@@ -147,7 +146,7 @@ val quoted : expression =
147146
[{Ppxlib__.Import.pvb_pat =
148147
{Ppxlib__.Import.ppat_desc =
149148
Ppxlib__.Import.Ppat_var
150-
{Ppxlib__.Import.txt = "__1";
149+
{Ppxlib__.Import.txt = "__2";
151150
loc =
152151
{Ppxlib__.Import.loc_start =
153152
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
@@ -190,16 +189,49 @@ val quoted : expression =
190189
loc_ghost = true};
191190
ppat_loc_stack = []; ppat_attributes = []},
192191
{Ppxlib__.Import.pexp_desc =
193-
Ppxlib__.Import.Pexp_ident
194-
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "bar";
195-
loc =
196-
{Ppxlib__.Import.loc_start =
197-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
198-
pos_bol = 0; pos_cnum = -1};
199-
loc_end =
200-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
201-
pos_bol = 0; pos_cnum = -1};
202-
loc_ghost = true}};
192+
Ppxlib__.Import.Pexp_apply
193+
({Ppxlib__.Import.pexp_desc =
194+
Ppxlib__.Import.Pexp_ident
195+
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "foo";
196+
loc =
197+
{Ppxlib__.Import.loc_start =
198+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
199+
pos_bol = 0; pos_cnum = -1};
200+
loc_end =
201+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
202+
pos_bol = 0; pos_cnum = -1};
203+
loc_ghost = true}};
204+
pexp_loc =
205+
{Ppxlib__.Import.loc_start =
206+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
207+
pos_bol = 0; pos_cnum = -1};
208+
loc_end =
209+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
210+
pos_bol = 0; pos_cnum = -1};
211+
loc_ghost = true};
212+
pexp_loc_stack = []; pexp_attributes = []},
213+
[(Ppxlib__.Import.Nolabel,
214+
{Ppxlib__.Import.pexp_desc =
215+
Ppxlib__.Import.Pexp_construct
216+
({Ppxlib__.Import.txt = Ppxlib__.Import.Lident "()";
217+
loc =
218+
{Ppxlib__.Import.loc_start =
219+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
220+
pos_bol = 0; pos_cnum = -1};
221+
loc_end =
222+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
223+
pos_bol = 0; pos_cnum = -1};
224+
loc_ghost = true}},
225+
None);
226+
pexp_loc =
227+
{Ppxlib__.Import.loc_start =
228+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
229+
pos_bol = 0; pos_cnum = -1};
230+
loc_end =
231+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
232+
pos_bol = 0; pos_cnum = -1};
233+
loc_ghost = true};
234+
pexp_loc_stack = []; pexp_attributes = []})]);
203235
pexp_loc =
204236
{Ppxlib__.Import.loc_start =
205237
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
@@ -230,7 +262,7 @@ val quoted : expression =
230262
{Ppxlib__.Import.pvb_pat =
231263
{Ppxlib__.Import.ppat_desc =
232264
Ppxlib__.Import.Ppat_var
233-
{Ppxlib__.Import.txt = "__0";
265+
{Ppxlib__.Import.txt = "__1";
234266
loc =
235267
{Ppxlib__.Import.loc_start =
236268
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
@@ -250,48 +282,16 @@ val quoted : expression =
250282
ppat_loc_stack = []; ppat_attributes = []};
251283
pvb_expr =
252284
{Ppxlib__.Import.pexp_desc =
253-
Ppxlib__.Import.Pexp_fun (Ppxlib__.Import.Nolabel, None,
254-
{Ppxlib__.Import.ppat_desc =
255-
Ppxlib__.Import.Ppat_construct
256-
({Ppxlib__.Import.txt = Ppxlib__.Import.Lident "()";
257-
loc =
258-
{Ppxlib__.Import.loc_start =
259-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
260-
pos_bol = 0; pos_cnum = -1};
261-
loc_end =
262-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
263-
pos_bol = 0; pos_cnum = -1};
264-
loc_ghost = true}},
265-
None);
266-
ppat_loc =
267-
{Ppxlib__.Import.loc_start =
268-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
269-
pos_bol = 0; pos_cnum = -1};
270-
loc_end =
271-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
272-
pos_bol = 0; pos_cnum = -1};
273-
loc_ghost = true};
274-
ppat_loc_stack = []; ppat_attributes = []},
275-
{Ppxlib__.Import.pexp_desc =
276-
Ppxlib__.Import.Pexp_ident
277-
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "foo";
278-
loc =
279-
{Ppxlib__.Import.loc_start =
280-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
281-
pos_bol = 0; pos_cnum = -1};
282-
loc_end =
283-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
284-
pos_bol = 0; pos_cnum = -1};
285-
loc_ghost = true}};
286-
pexp_loc =
285+
Ppxlib__.Import.Pexp_ident
286+
{Ppxlib__.Import.txt = Ppxlib__.Import.Lident "bar";
287+
loc =
287288
{Ppxlib__.Import.loc_start =
288289
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
289290
pos_bol = 0; pos_cnum = -1};
290291
loc_end =
291292
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
292293
pos_bol = 0; pos_cnum = -1};
293-
loc_ghost = true};
294-
pexp_loc_stack = []; pexp_attributes = []});
294+
loc_ghost = true}};
295295
pexp_loc =
296296
{Ppxlib__.Import.loc_start =
297297
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
@@ -309,30 +309,34 @@ val quoted : expression =
309309
loc_end =
310310
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1; pos_bol = 0;
311311
pos_cnum = -1};
312-
loc_ghost = true}}],
313-
{Ppxlib__.Import.pexp_desc =
314-
Ppxlib__.Import.Pexp_construct
315-
({Ppxlib__.Import.txt = Ppxlib__.Import.Lident "::";
316-
loc =
317-
{Ppxlib__.Import.loc_start =
318-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
319-
pos_bol = 0; pos_cnum = -1};
320-
loc_end =
321-
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
322-
pos_bol = 0; pos_cnum = -1};
323-
loc_ghost = true}},
324-
Some
325-
{Ppxlib__.Import.pexp_desc =
326-
Ppxlib__.Import.Pexp_tuple
327-
[{Ppxlib__.Import.pexp_desc = Ppxlib__.Import.Pexp_apply (...);
328-
pexp_loc = ...; pexp_loc_stack = ...; pexp_attributes = ...};
329-
...];
330-
pexp_loc = ...; pexp_loc_stack = ...; pexp_attributes = ...});
331-
pexp_loc = ...; pexp_loc_stack = ...; pexp_attributes = ...});
312+
loc_ghost = true}};
313+
{Ppxlib__.Import.pvb_pat =
314+
{Ppxlib__.Import.ppat_desc =
315+
Ppxlib__.Import.Ppat_var
316+
{Ppxlib__.Import.txt = "__0";
317+
loc =
318+
{Ppxlib__.Import.loc_start =
319+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
320+
pos_bol = 0; pos_cnum = -1};
321+
loc_end =
322+
{Ppxlib__.Import.pos_fname = "_none_"; pos_lnum = 1;
323+
pos_bol = 0; pos_cnum = -1};
324+
loc_ghost = true}};
325+
ppat_loc =
326+
{Ppxlib__.Import.loc_start =
327+
{Ppxlib__.Import.pos_fname =
328+
"_no"... (* string length 6; truncated *);
329+
pos_lnum = 1; pos_bol = 0; pos_cnum = -1};
330+
loc_end = ...; loc_ghost = ...};
331+
ppat_loc_stack = ...; ppat_attributes = ...};
332+
pvb_expr = ...; pvb_attributes = ...; pvb_loc = ...};
333+
...],
334+
...);
332335
pexp_loc = ...; pexp_loc_stack = ...; pexp_attributes = ...}
333336
|}]
334337

335338
Pprintast.string_of_expression quoted;;
336339
[%%expect{|
337-
- : string = "let rec __1 () = bar\nand __0 () = foo in [__0 (); __1 ()]"
340+
- : string =
341+
"let rec __2 () = foo ()\nand __1 = bar\nand __0 = foo in [__0; __1; __2 ()]"
338342
|}]

0 commit comments

Comments
 (0)