Skip to content

Commit 058c893

Browse files
authored
Make bind & tighter than mod in jkind parsing (#3076)
* make `&` tighter than `mod` in jkind parsing Signed-off-by: David Vulakh <dvulakh@janestreet.com> * forbid `k mod m & l` without parens around `mod` Signed-off-by: David Vulakh <dvulakh@janestreet.com> * reflect new syntax in tests Signed-off-by: David Vulakh <dvulakh@janestreet.com> * revert 1eea0c2 Signed-off-by: David Vulakh <dvulakh@janestreet.com> * add typing test to demo `&` and `mod` precedence Note that ``` type t3 : any & (any mod non_null) = #(t1 * t2);; ``` Does not have the same behavior as ``` type t3 : any & any mod non_null = #(t1 * t2);; ``` Signed-off-by: David Vulakh <dvulakh@janestreet.com> * add test to [pprintast_unconditional.ml] the test currently fails, so yes, we need to update the kind printer Signed-off-by: David Vulakh <dvulakh@janestreet.com> * add more parentheses in printer there are sometimes unnecessary parentheses, but that seems fine in the name of both clarity of printed syntax and printer simplicity added a test with [with] along the way Signed-off-by: David Vulakh <dvulakh@janestreet.com> * fix oprint and change the jkind bits of pprint ast to use [Misc.pp_parens_if] now that it's exposed Signed-off-by: David Vulakh <dvulakh@janestreet.com> --------- Signed-off-by: David Vulakh <dvulakh@janestreet.com>
1 parent b7d910d commit 058c893

File tree

7 files changed

+67
-30
lines changed

7 files changed

+67
-30
lines changed

ocaml/parsing/parser.mly

+3-2
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@ The precedences must be listed from low to high.
10731073
%left INFIXOP2 PLUS PLUSDOT MINUS MINUSDOT PLUSEQ /* expr (e OP e OP e) */
10741074
%left PERCENT INFIXOP3 MOD STAR /* expr (e OP e OP e) */
10751075
%right INFIXOP4 /* expr (e OP e OP e) */
1076+
%nonassoc prec_unboxed_product_kind
10761077
%nonassoc prec_unary_minus prec_unary_plus /* unary - */
10771078
%nonassoc prec_constant_constructor /* cf. simple_expr (C versus C x) */
10781079
%nonassoc prec_constr_appl /* above AS BAR COLONCOLON COMMA */
@@ -3902,11 +3903,11 @@ jkind:
39023903
;
39033904

39043905
reverse_product_jkind :
3905-
| jkind1 = jkind AMPERSAND jkind2 = jkind %prec below_EQUAL
3906+
| jkind1 = jkind AMPERSAND jkind2 = jkind %prec prec_unboxed_product_kind
39063907
{ [jkind2; jkind1] }
39073908
| jkinds = reverse_product_jkind
39083909
AMPERSAND
3909-
jkind = jkind %prec below_EQUAL
3910+
jkind = jkind %prec prec_unboxed_product_kind
39103911
{ jkind :: jkinds }
39113912

39123913
jkind_annotation: (* : jkind_annotation *)

ocaml/parsing/pprintast.ml

+11-7
Original file line numberDiff line numberDiff line change
@@ -437,17 +437,21 @@ and jkind ?(nested = false) ctxt f k = match (k : Jane_syntax.Jkind.t) with
437437
begin match modes with
438438
| [] -> Misc.fatal_error "malformed jkind annotation"
439439
| _ :: _ ->
440-
pp f "%a mod %a"
441-
(jkind ~nested:true ctxt) t
442-
(pp_print_list ~pp_sep:pp_print_space mode) modes
440+
Misc.pp_parens_if nested (fun f (t, modes) ->
441+
pp f "%a mod %a"
442+
(jkind ~nested:true ctxt) t
443+
(pp_print_list ~pp_sep:pp_print_space mode) modes
444+
) f (t, modes)
443445
end
444446
| With (t, ty) ->
445-
pp f "%a with %a" (jkind ctxt) t (core_type ctxt) ty
447+
Misc.pp_parens_if nested (fun f (t, ty) ->
448+
pp f "%a with %a" (jkind ~nested:true ctxt) t (core_type ctxt) ty
449+
) f (t, ty)
446450
| Kind_of ty -> pp f "kind_of_ %a" (core_type ctxt) ty
447451
| Product ts ->
448-
if nested then pp f "(";
449-
pp f "%a" (list (jkind ~nested:true ctxt) ~sep:"@;&@;") ts;
450-
if nested then pp f ")"
452+
Misc.pp_parens_if nested (fun f ts ->
453+
pp f "%a" (list (jkind ~nested:true ctxt) ~sep:"@;&@;") ts
454+
) f ts
451455

452456
and jkind_annotation ctxt f annot = jkind ctxt f annot.txt
453457

ocaml/testsuite/tests/language-extensions/pprintast_unconditional.ml

+6-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ module Example = struct
5050
() = () in f"
5151
let utuple_exp = parse expression
5252
"let #(x,y) : #(int * int) = #(1,2) in \
53-
let #(a,#(b,c)) : ('a : value & (value & value)) = #(3,#(4,5)) in
54-
x + y + a + b + c"
53+
let #(a,#(b,c)) : ('a : value & (value & value)) = #(3,#(4,5)) in \
54+
let #(i,j) : ('b : value mod m & (value mod l)) = #(6,7) in \
55+
let #(s,t) : ('c : value mod m & value mod l) = #(7,8) in \
56+
let #(k,l) : ('d : value with t & (value with t)) = #(6,7) in \
57+
let #(u,v) : ('e : value with t & value with t) = #(7,8) in \
58+
x + y + a + b + c + i + j + s + t + k + l + u + v"
5559

5660
let modal_kind_struct =
5761
parse module_expr "struct \

ocaml/testsuite/tests/language-extensions/pprintast_unconditional.reference

+10-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ fun_with_modes_on_arg:
4242
utuple_exp:
4343
let #(x, y) : #(int * int) = #(1, 2) in
4444
let #(a, #(b, c)) : ('a : value & (value & value)) = #(3, #(4, 5)) in
45-
(((x + y) + a) + b) + c
45+
let #(i, j) : ('b : (value mod m) & (value mod l)) = #(6, 7) in
46+
let #(s, t) : ('c : ((value mod m) & value) mod l) = #(7, 8) in
47+
let #(k, l) : ('d : (value with t) & (value with t)) = #(6, 7) in
48+
let #(u, v) : ('e : ((value with t) & value) with t) = #(7, 8) in
49+
(((((((((((x + y) + a) + b) + c) + i) + j) + s) + t) + k) + l) + u) + v
4650

4751
longident: No.Longidents.Require.extensions
4852

@@ -172,7 +176,11 @@ fun_with_modes_on_arg:
172176
utuple_exp:
173177
let #(x, y) : #(int * int) = #(1, 2) in
174178
let #(a, #(b, c)) : ('a : value & (value & value)) = #(3, #(4, 5)) in
175-
(((x + y) + a) + b) + c
179+
let #(i, j) : ('b : (value mod m) & (value mod l)) = #(6, 7) in
180+
let #(s, t) : ('c : ((value mod m) & value) mod l) = #(7, 8) in
181+
let #(k, l) : ('d : (value with t) & (value with t)) = #(6, 7) in
182+
let #(u, v) : ('e : ((value with t) & value) with t) = #(7, 8) in
183+
(((((((((((x + y) + a) + b) + c) + i) + j) + s) + t) + k) + l) + u) + v
176184

177185
longident: No.Longidents.Require.extensions
178186

ocaml/testsuite/tests/typing-layouts-products/basics_alpha.ml

+21-12
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type t3 = #(t1 * t2)
3131

3232
type t1 : any mod non_null
3333
type t2 : value
34-
type t3 : (any & value) mod non_null = #(t1 * t2);;
34+
type t3 : any & value mod non_null = #(t1 * t2);;
3535
[%%expect{|
3636
type t1 : any mod non_null
3737
type t2
@@ -40,13 +40,22 @@ type t3 = #(t1 * t2)
4040

4141
type t1 : any mod non_null
4242
type t2 : value
43-
type t3 : any mod non_null & value mod non_null = #(t1 * t2);;
43+
type t3 : (any mod non_null) & (value mod non_null) = #(t1 * t2);;
4444
[%%expect{|
4545
type t1 : any mod non_null
4646
type t2
4747
type t3 = #(t1 * t2)
4848
|}]
4949

50+
type t1 : any
51+
type t2 : any mod non_null
52+
type t3 : any & (any mod non_null) = #(t1 * t2);;
53+
[%%expect{|
54+
type t1 : any
55+
type t2 : any mod non_null
56+
type t3 = #(t1 * t2)
57+
|}]
58+
5059
(* Should not be allowed. *)
5160
type t1 : any
5261
type t2 : any mod non_null
@@ -65,32 +74,32 @@ Error: The kind of type "#(t1 * t2)" is any & any
6574

6675
type t1 : any
6776
type t2 : any mod non_null
68-
type t3 : (any & any) mod non_null = #(t1 * t2);;
77+
type t3 : any & any mod non_null = #(t1 * t2);;
6978
[%%expect{|
7079
type t1 : any
7180
type t2 : any mod non_null
72-
Line 3, characters 0-47:
73-
3 | type t3 : (any & any) mod non_null = #(t1 * t2);;
74-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
81+
Line 3, characters 0-45:
82+
3 | type t3 : any & any mod non_null = #(t1 * t2);;
83+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7584
Error: The kind of type "#(t1 * t2)" is any & any
7685
because it is an unboxed tuple.
7786
But the kind of type "#(t1 * t2)" must be a subkind of
7887
any_non_null & any_non_null
79-
because of the definition of t3 at line 3, characters 0-47.
88+
because of the definition of t3 at line 3, characters 0-45.
8089
|}]
8190

8291
type t1 : any
8392
type t2 : any mod non_null
84-
type t3 : any mod non_null & any mod non_null = #(t1 * t2);;
93+
type t3 : (any mod non_null) & (any mod non_null) = #(t1 * t2);;
8594
[%%expect{|
8695
type t1 : any
8796
type t2 : any mod non_null
88-
Line 3, characters 0-58:
89-
3 | type t3 : any mod non_null & any mod non_null = #(t1 * t2);;
90-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
97+
Line 3, characters 0-62:
98+
3 | type t3 : (any mod non_null) & (any mod non_null) = #(t1 * t2);;
99+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
91100
Error: The kind of type "#(t1 * t2)" is any & any
92101
because it is an unboxed tuple.
93102
But the kind of type "#(t1 * t2)" must be a subkind of
94103
any_non_null & any_non_null
95-
because of the definition of t3 at line 3, characters 0-58.
104+
because of the definition of t3 at line 3, characters 0-62.
96105
|}]

ocaml/typing/oprint.ml

+7-5
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,13 @@ let print_out_jkind_const ppf ojkind =
342342
| Ojkind_const_default -> fprintf ppf "_"
343343
| Ojkind_const_abbreviation abbrev -> fprintf ppf "%s" abbrev
344344
| Ojkind_const_mod (base, modes) ->
345-
fprintf ppf "%a mod @[%a@]" (pp_element ~nested) base
346-
(pp_print_list
347-
~pp_sep:(fun ppf () -> fprintf ppf "@ ")
348-
(fun ppf -> fprintf ppf "%s"))
349-
modes
345+
Misc.pp_parens_if nested (fun ppf (base, modes) ->
346+
fprintf ppf "%a mod @[%a@]" (pp_element ~nested:true) base
347+
(pp_print_list
348+
~pp_sep:(fun ppf () -> fprintf ppf "@ ")
349+
(fun ppf -> fprintf ppf "%s"))
350+
modes
351+
) ppf (base, modes)
350352
| Ojkind_const_product ts ->
351353
let pp_sep ppf () = Format.fprintf ppf "@ & " in
352354
Misc.pp_nested_list ~nested ~pp_element ~pp_sep ppf ts

ocaml/utils/misc.mli

+9
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,15 @@ val pp_two_columns :
693693
v}
694694
*)
695695

696+
val pp_parens_if :
697+
bool
698+
-> (Format.formatter -> 'a -> unit)
699+
-> Format.formatter
700+
-> 'a
701+
-> unit
702+
(** [pp_parens_if bool formatter ppf arg] prints [formatter ppf arg], wrapping it with
703+
[()] if [bool] is true. *)
704+
696705
val pp_nested_list :
697706
nested:bool
698707
-> pp_element:(nested:bool -> Format.formatter -> 'a -> unit)

0 commit comments

Comments
 (0)