Skip to content

Commit f989f1a

Browse files
committed
letop-punning for extension nodes
1 parent 7ec4b50 commit f989f1a

File tree

13 files changed

+66
-24
lines changed

13 files changed

+66
-24
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ profile. This started with version 0.26.0.
1414
`let+ x in ...` when `letop-punning=always`. With `letop-punning=never`, it
1515
becomes `let+ x = x in ...`. The default is `preserve`, which will
1616
only use punning when it exists in the source.
17+
This also applies to `let%ext` bindings (#<PR_NUMBER>, @WardBrian).
1718

1819
### Fixed
1920

doc/manpage_ocamlformat.mld

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,14 @@ OPTIONS (CODE FORMATTING STYLE)
272272
a single line. The default value is compact.
273273

274274
--letop-punning={preserve|always|never}
275-
Name punning in bindings using extended let operators. preserve
276-
uses let-punning only when it exists in the source; the code "let*
277-
foo and* z = z in ..." will be left unchanged. always uses
278-
let-punning whenever possible; the code "let* foo and* z = z in
279-
..." will be rewritten to "let* foo and* z in ...". never never
280-
uses let-punning; the code "let* foo and* z = z in ..." will be
281-
rewritten to "let* foo = foo and* z = z in ...". The default value
282-
is preserve.
275+
Name punning in bindings using extended let operators and let%ext
276+
bindings. preserve uses let-punning only when it exists in the
277+
source; the code "let* foo and* z = z in ..." will be left
278+
unchanged. always uses let-punning whenever possible; the code
279+
"let* foo and* z = z in ..." will be rewritten to "let* foo and* z
280+
in ...". never never uses let-punning; the code "let* foo and* z =
281+
z in ..." will be rewritten to "let* foo = foo and* z = z in ...".
282+
The default value is preserve.
283283

284284
--line-endings={lf|crlf}
285285
Line endings used. lf uses Unix line endings. crlf uses Windows

lib/Conf.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,10 @@ module Formatting = struct
998998
(fun conf -> conf.fmt_opts.let_module)
999999

10001000
let letop_punning =
1001-
let doc = "Name punning in bindings using extended let operators." in
1001+
let doc =
1002+
"Name punning in bindings using extended let operators and \
1003+
$(i,let%ext) bindings."
1004+
in
10021005
let names = ["letop-punning"] in
10031006
let all =
10041007
[ Decl.Value.make ~name:"preserve" `Preserve

lib/Extended_ast.ml

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,15 +238,47 @@ module Parse = struct
238238
| None -> b.pbop_is_pun
239239
| Some false -> false
240240
| Some true -> (
241-
match (b.pbop_pat.ppat_desc, b.pbop_exp.pexp_desc) with
242-
| Ppat_var {txt= v; _}, Pexp_ident {txt= Lident e; _} ->
243-
String.equal v e
244-
| _ -> false )
241+
b.pbop_is_pun
242+
||
243+
match (b.pbop_pat.ppat_desc, b.pbop_exp.pexp_desc) with
244+
| Ppat_var {txt= v; _}, Pexp_ident {txt= Lident e; _} ->
245+
String.equal v e
246+
| _ -> false )
245247
in
246248
{b with pbop_loc= {b.pbop_loc with loc_start; loc_end}; pbop_is_pun}
247249
in
248250
Ast_mapper.default_mapper.binding_op m b'
249251
in
252+
let value_bindings (m : Ast_mapper.mapper) vbs =
253+
let punning is_extension vb =
254+
let is_extension =
255+
is_extension || Option.is_some vb.pvb_attributes.attrs_extension
256+
in
257+
let pvb_is_pun =
258+
is_extension
259+
&&
260+
match prefer_let_puns with
261+
| None -> vb.pvb_is_pun
262+
| Some false -> false
263+
| Some true -> (
264+
vb.pvb_is_pun
265+
||
266+
match (vb.pvb_pat.ppat_desc, vb.pvb_body) with
267+
| ( Ppat_var {txt= v; _}
268+
, Pfunction_body {pexp_desc= Pexp_ident {txt= Lident e; _}; _}
269+
) ->
270+
String.equal v e
271+
| _ -> false )
272+
in
273+
(is_extension, {vb with pvb_is_pun})
274+
in
275+
let vbs' =
276+
{ vbs with
277+
pvbs_bindings=
278+
snd @@ List.fold_map ~init:false ~f:punning vbs.pvbs_bindings }
279+
in
280+
Ast_mapper.default_mapper.value_bindings m vbs'
281+
in
250282
let pat m = function
251283
| {ppat_desc= Ppat_cons (_ :: _ :: _ :: _ as l); _} as p
252284
when match List.last_exn l with
@@ -315,7 +347,7 @@ module Parse = struct
315347
{p with pexp_desc= Pexp_tuple l}
316348
| e -> Ast_mapper.default_mapper.expr m e
317349
in
318-
Ast_mapper.{default_mapper with expr; pat; binding_op}
350+
Ast_mapper.{default_mapper with expr; pat; binding_op; value_bindings}
319351

320352
let ast (type a) (fg : a t) ~ocaml_version ~preserve_beginend
321353
~prefer_let_puns ~input_name str : a =

test/failing/tests/letop_broken.ml.broken-ref

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ ocamlformat: Cannot process "tests/letop_broken.ml".
22
Please report this bug at https://github.com/ocaml-ppx/ocamlformat/issues.
33
BUG: comment changed.
44
File "tests/letop_broken.ml", line 13, characters 33-40:
5+
Error: comment (* 3 *) dropped.
6+
BUG: comment changed.
7+
File "tests/letop_broken.ml", line 16, characters 36-43:
58
Error: comment (* 3 *) dropped.
69
BUG: comment changed.
710
File "tests/letop_broken.ml", line 13, characters 43-50:
11+
Error: comment (* 4 *) dropped.
12+
BUG: comment changed.
13+
File "tests/letop_broken.ml", line 16, characters 46-53:
814
Error: comment (* 4 *) dropped.

test/passing/refs.ahrefs/let_punning-denied.ml.ref

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ let p =
1515
x, y, z
1616

1717
let q =
18-
let%foo x
18+
let%foo x = x
1919
and y = y
20-
and z in
20+
and z = z in
2121
x, y, z

test/passing/refs.ahrefs/let_punning-preferred.ml.ref

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ let p =
1616

1717
let q =
1818
let%foo x
19-
and y = y
19+
and y
2020
and z in
2121
x, y, z

test/passing/refs.default/let_punning-denied.ml.ref

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ let p =
1010
(x, y, z)
1111

1212
let q =
13-
let%foo x and y = y and z in
13+
let%foo x = x and y = y and z = z in
1414
(x, y, z)

test/passing/refs.default/let_punning-preferred.ml.ref

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ let p =
1010
(x, y, z)
1111

1212
let q =
13-
let%foo x and y = y and z in
13+
let%foo x and y and z in
1414
(x, y, z)

test/passing/refs.janestreet/let_punning-denied.ml.ref

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ let p =
1313
;;
1414

1515
let q =
16-
let%foo x
16+
let%foo x = x
1717
and y = y
18-
and z in
18+
and z = z in
1919
x, y, z
2020
;;

0 commit comments

Comments
 (0)