@@ -812,6 +812,8 @@ module rec In_ctx : sig
812
812
val sub_sig : ctx :T .t -> signature_item -> signature_item xt
813
813
814
814
val sub_str : ctx :T .t -> structure_item -> structure_item xt
815
+
816
+ val sub_fun_body : ctx :T .t -> function_body -> function_body xt
815
817
end = struct
816
818
open Requires_sub_terms
817
819
@@ -846,6 +848,8 @@ end = struct
846
848
let sub_sig ~ctx sig_ = {ctx; ast= sig_}
847
849
848
850
let sub_str ~ctx str = {ctx; ast= str}
851
+
852
+ let sub_fun_body ~ctx ast = {ctx; ast}
849
853
end
850
854
851
855
(* * Operations determining precedence and necessary parenthesization of terms
@@ -1202,9 +1206,15 @@ end = struct
1202
1206
| Ppat_constraint (p , _ ) -> p == pat
1203
1207
| _ -> false
1204
1208
in
1205
- let check_bindings l =
1206
- List. exists l ~f: (fun {pvb_pat; _} -> check_subpat pvb_pat)
1209
+ let check_cases = List. exists ~f: (fun c -> c.pc_lhs == pat) in
1210
+ let check_binding {pvb_pat; pvb_body; _} =
1211
+ check_subpat pvb_pat
1212
+ ||
1213
+ match pvb_body with
1214
+ | Pfunction_body _ -> false
1215
+ | Pfunction_cases (cases , _ , _ ) -> check_cases cases
1207
1216
in
1217
+ let check_bindings l = List. exists l ~f: check_binding in
1208
1218
let check_param_val (_ , _ , p ) = p == pat in
1209
1219
let check_expr_function_param param =
1210
1220
match param.pparam_desc with
@@ -1217,7 +1227,6 @@ end = struct
1217
1227
let check_class_function_params =
1218
1228
List. exists ~f: check_class_function_param
1219
1229
in
1220
- let check_cases = List. exists ~f: (fun c -> c.pc_lhs == pat) in
1221
1230
match ctx with
1222
1231
| Pld (PPat (p1 , _ )) -> assert (p1 == pat)
1223
1232
| Pld _ -> assert false
@@ -1283,7 +1292,7 @@ end = struct
1283
1292
| Fpe ctx -> assert (check_expr_function_param ctx)
1284
1293
| Fpc ctx -> assert (check_class_function_param ctx)
1285
1294
| Vc _ -> assert false
1286
- | Lb x -> assert (x.pvb_pat == pat )
1295
+ | Lb x -> assert (check_binding x )
1287
1296
| Bo x -> assert (x.pbop_pat == pat)
1288
1297
| Mb _ -> assert false
1289
1298
| Md _ -> assert false
@@ -1351,6 +1360,10 @@ end = struct
1351
1360
| {pc_rhs; _} when pc_rhs == exp -> true
1352
1361
| _ -> false )
1353
1362
in
1363
+ let check_fun_body = function
1364
+ | Pfunction_body body -> body == exp
1365
+ | Pfunction_cases (cases , _ , _ ) -> check_cases cases
1366
+ in
1354
1367
match ctx with
1355
1368
| Pld (PPat (_ , Some e1 )) -> assert (e1 == exp)
1356
1369
| Pld _ -> assert false
@@ -1365,8 +1378,8 @@ end = struct
1365
1378
| Pexp_object _ -> assert false
1366
1379
| Pexp_let ({pvbs_bindings; _} , e , _ ) ->
1367
1380
assert (
1368
- List. exists pvbs_bindings ~f: (fun {pvb_expr ; _} ->
1369
- pvb_expr == exp )
1381
+ List. exists pvbs_bindings ~f: (fun {pvb_body ; _} ->
1382
+ check_fun_body pvb_body )
1370
1383
|| e == exp )
1371
1384
| Pexp_letop {let_; ands; body; loc_in = _ } ->
1372
1385
let f {pbop_exp; _} = pbop_exp == exp in
@@ -1375,13 +1388,9 @@ end = struct
1375
1388
| Pexp_match (_ , cases ) | Pexp_try (_ , cases ) ->
1376
1389
assert (check_cases cases)
1377
1390
| Pexp_function (params , _ , body ) ->
1378
- let check_body =
1379
- match body with
1380
- | Pfunction_body body -> body == exp
1381
- | Pfunction_cases (cases , _ , _ ) -> check_cases cases
1382
- in
1383
1391
assert (
1384
- List. exists ~f: check_expr_function_param params || check_body )
1392
+ List. exists ~f: check_expr_function_param params
1393
+ || check_fun_body body )
1385
1394
| Pexp_indexop_access {pia_lhs; pia_kind = Builtin idx ; pia_rhs; _} ->
1386
1395
assert (
1387
1396
pia_lhs == exp || idx == exp
@@ -1431,7 +1440,7 @@ end = struct
1431
1440
| Fpe ctx -> assert (check_expr_function_param ctx)
1432
1441
| Fpc ctx -> assert (check_class_function_param ctx)
1433
1442
| Vc _ -> assert false
1434
- | Lb x -> assert (x.pvb_expr == exp )
1443
+ | Lb x -> assert (check_fun_body x.pvb_body )
1435
1444
| Bo x -> assert (x.pbop_exp == exp)
1436
1445
| Mb _ -> assert false
1437
1446
| Md _ -> assert false
@@ -1440,8 +1449,8 @@ end = struct
1440
1449
| Pstr_eval (e0 , _ ) -> assert (e0 == exp)
1441
1450
| Pstr_value {pvbs_bindings; _} ->
1442
1451
assert (
1443
- List. exists pvbs_bindings ~f: (fun {pvb_expr ; _} ->
1444
- pvb_expr == exp ) )
1452
+ List. exists pvbs_bindings ~f: (fun {pvb_body ; _} ->
1453
+ check_fun_body pvb_body ) )
1445
1454
| Pstr_extension ((_ , ext ), _ ) -> assert (check_extensions ext)
1446
1455
| Pstr_primitive _ | Pstr_type _ | Pstr_typext _ | Pstr_exception _
1447
1456
| Pstr_module _ | Pstr_recmodule _ | Pstr_modtype _ | Pstr_open _
@@ -1457,8 +1466,8 @@ end = struct
1457
1466
| Pcl_structure _ -> false
1458
1467
| Pcl_apply (_ , l ) -> List. exists l ~f: (fun (_ , e ) -> e == exp)
1459
1468
| Pcl_let ({pvbs_bindings; _} , _ , _ ) ->
1460
- List. exists pvbs_bindings ~f: (fun {pvb_expr ; _} ->
1461
- pvb_expr == exp )
1469
+ List. exists pvbs_bindings ~f: (fun {pvb_body ; _} ->
1470
+ check_fun_body pvb_body )
1462
1471
| Pcl_constraint _ -> false
1463
1472
| Pcl_extension _ -> false
1464
1473
| Pcl_open _ -> false
@@ -1866,6 +1875,23 @@ end = struct
1866
1875
| Ppat_tuple _ -> true
1867
1876
| _ -> false
1868
1877
1878
+ let parenze_pat_in_bindings bindings pat =
1879
+ let parenze_pat_in_binding ~pvb_constraint =
1880
+ (* Some patterns must be parenthesed when followed by a colon. *)
1881
+ (exposed_right_colon pat && Option. is_some pvb_constraint)
1882
+ ||
1883
+ match pat.ppat_desc with
1884
+ | Ppat_construct (_, Some _)
1885
+ | Ppat_variant (_, Some _)
1886
+ | Ppat_cons _ | Ppat_alias _ | Ppat_or _ ->
1887
+ (* Add disambiguation parentheses that are not necessary. *)
1888
+ true
1889
+ | _ -> false
1890
+ in
1891
+ List. exists bindings ~f: (fun {pvb_pat; pvb_constraint; _} ->
1892
+ (* [pat] appears on the left side of a binding. *)
1893
+ pvb_pat == pat && parenze_pat_in_binding ~pvb_constraint )
1894
+
1869
1895
(* * [parenze_pat {ctx; ast}] holds when pattern [ast] should be
1870
1896
parenthesized in context [ctx]. *)
1871
1897
let parenze_pat ({ctx; ast = pat } as xpat ) =
@@ -1902,6 +1928,11 @@ end = struct
1902
1928
| Ppat_or _ | Ppat_alias _ ) ) ->
1903
1929
true
1904
1930
| Bo {pbop_typ = Some _ ; _} , (Ppat_any | Ppat_tuple _ ) -> true
1931
+ | Exp {pexp_desc= Pexp_function (_, _, Pfunction_body _); _}, Ppat_or _
1932
+ | ( Exp {pexp_desc= Pexp_function (_, _, Pfunction_body _); _}
1933
+ , ( Ppat_construct _ | Ppat_cons _ | Ppat_lazy _ | Ppat_tuple _
1934
+ | Ppat_variant _ ) ) ->
1935
+ true
1905
1936
| _, Ppat_constraint _
1906
1937
| _, Ppat_unpack _
1907
1938
| ( Pat
@@ -1931,18 +1962,14 @@ end = struct
1931
1962
| Pat {ppat_desc= Ppat_tuple _; _}, Ppat_tuple _
1932
1963
| Pat _, Ppat_lazy _
1933
1964
| Pat _, Ppat_exception _
1934
- | Exp {pexp_desc= Pexp_function (_, _, Pfunction_body _); _}, Ppat_or _
1935
1965
| Cl {pcl_desc= Pcl_fun _; _}, Ppat_variant (_, Some _)
1936
1966
| Cl {pcl_desc= Pcl_fun _; _}, Ppat_tuple _
1937
1967
| Cl {pcl_desc= Pcl_fun _; _}, Ppat_construct _
1938
1968
| Cl {pcl_desc= Pcl_fun _; _}, Ppat_alias _
1939
1969
| Cl {pcl_desc= Pcl_fun _; _}, Ppat_lazy _
1940
- | (Exp {pexp_desc= Pexp_letop _; _} | Bo _), Ppat_exception _
1941
- | ( Exp {pexp_desc= Pexp_function (_, _, Pfunction_body _); _}
1942
- , ( Ppat_construct _ | Ppat_cons _ | Ppat_lazy _ | Ppat_tuple _
1943
- | Ppat_variant _ ) ) ->
1970
+ | (Exp {pexp_desc= Pexp_letop _; _} | Bo _ ), Ppat_exception _ ->
1944
1971
true
1945
- | (Str _ | Exp _ ), Ppat_lazy _ -> true
1972
+ | (Str _ | Exp _ | Lb _ ), Ppat_lazy _ -> true
1946
1973
| ( (Fpe _ | Fpc _)
1947
1974
, ( Ppat_tuple _ | Ppat_construct _ | Ppat_alias _ | Ppat_variant _
1948
1975
| Ppat_lazy _ | Ppat_exception _ | Ppat_or _ ) )
@@ -1953,23 +1980,36 @@ end = struct
1953
1980
| _ , Ppat_var _ when List. is_empty pat.ppat_attributes -> false
1954
1981
| ( ( Exp {pexp_desc= Pexp_let ({pvbs_bindings; _}, _, _); _}
1955
1982
| Str {pstr_desc= Pstr_value {pvbs_bindings; _}; _} )
1956
- , pat_desc ) -> (
1957
- match pat_desc with
1958
- | Ppat_construct (_, Some _)
1959
- | Ppat_variant (_, Some _)
1960
- | Ppat_cons _ | Ppat_alias _ | Ppat_constraint _ | Ppat_lazy _
1961
- | Ppat_or _ ->
1962
- (* Add disambiguation parentheses that are not necessary. *)
1963
- true
1964
- | _ when exposed_right_colon pat ->
1965
- (* Some patterns must be parenthesed when followed by a colon. *)
1966
- let pvb =
1967
- List. find_exn pvbs_bindings ~f: (fun pvb -> pvb.pvb_pat == pat)
1968
- in
1969
- Option. is_some pvb.pvb_constraint
1970
- | _ -> false )
1983
+ , _ )
1984
+ when parenze_pat_in_bindings pvbs_bindings pat ->
1985
+ true
1986
+ | ( Lb {pvb_pat; _}
1987
+ , ( Ppat_construct (_, Some _)
1988
+ | Ppat_variant (_, Some _)
1989
+ | Ppat_cons _ | Ppat_alias _ | Ppat_or _ ) )
1990
+ when pvb_pat == pat ->
1991
+ (* Disambiguation parentheses *)
1992
+ true
1993
+ | Lb {pvb_pat; pvb_constraint= Some _; _}, _
1994
+ when pvb_pat == pat && exposed_right_colon pat ->
1995
+ true
1971
1996
| _ -> false
1972
1997
1998
+ (* Whether an expression in a let binding shouldn't be parenthesed,
1999
+ bypassing the other Ast rules. *)
2000
+ let dont_parenze_exp_in_bindings bindings exp =
2001
+ match exp.pexp_desc with
2002
+ | Pexp_function ([] , None, (Pfunction_cases _ as fun_body )) ->
2003
+ (* [fun_body] is the body of the let binding and shouldn't be
2004
+ parenthesed. [exp] is a synthetic expression constructed in the
2005
+ formatting code. *)
2006
+ List. exists bindings ~f: (fun {pvb_body; _} -> pvb_body == fun_body)
2007
+ | _ -> false
2008
+
2009
+ let ctx_sensitive_to_trailing_attributes = function
2010
+ | Lb _ -> false
2011
+ | _ -> true
2012
+
1973
2013
let marked_parenzed_inner_nested_match =
1974
2014
let memo = Hashtbl.Poly. create () in
1975
2015
register_reset (fun () -> Hashtbl. clear memo) ;
@@ -2119,6 +2159,31 @@ end = struct
2119
2159
~default: exposed_
2120
2160
|> (ignore : bool -> _ )
2121
2161
2162
+ (* Whether to parenze an expr on the RHS of a match/try/function case. *)
2163
+ and parenze_exp_in_match_case cases exp =
2164
+ if ! leading_nested_match_parens then
2165
+ List. iter cases ~f: (fun {pc_rhs; _} ->
2166
+ mark_parenzed_inner_nested_match pc_rhs ) ;
2167
+ List. exists cases ~f: (fun {pc_rhs; _} -> pc_rhs == exp)
2168
+ && exposed_right_exp Match exp
2169
+
2170
+ (* Whether to parenze an expr on the RHS of a let binding.
2171
+ [dont_parenze_exp_in_bindings] must have been checked before. *)
2172
+ and parenze_exp_in_bindings bindings exp =
2173
+ List. exists bindings ~f: (fun {pvb_body; pvb_args; _} ->
2174
+ match pvb_body with
2175
+ | Pfunction_body
2176
+ ( {pexp_desc= Pexp_function ([] , None , Pfunction_cases _); _} as
2177
+ let_body )
2178
+ when let_body == exp ->
2179
+ (* Function with cases and no 'fun' keyword is in the body of a
2180
+ binding, parentheses are needed if the binding also defines
2181
+ arguments. *)
2182
+ not (List. is_empty pvb_args)
2183
+ | Pfunction_cases (cases , _ , _ ) ->
2184
+ parenze_exp_in_match_case cases exp
2185
+ | _ -> false )
2186
+
2122
2187
(* * [parenze_exp {ctx; ast}] holds when expression [ast] should be
2123
2188
parenthesized in context [ctx]. *)
2124
2189
and parenze_exp ({ctx; ast = exp } as xexp ) =
@@ -2173,7 +2238,19 @@ end = struct
2173
2238
||
2174
2239
match (ctx, exp) with
2175
2240
| Str {pstr_desc = Pstr_eval _ ; _} , _ -> false
2176
- | _ , {pexp_desc = Pexp_infix _ ; pexp_attributes = _ :: _ ; _} -> true
2241
+ | Lb pvb , _ when dont_parenze_exp_in_bindings [pvb] exp -> false
2242
+ | Exp {pexp_desc= Pexp_let ({pvbs_bindings; _}, _, _); _}, _
2243
+ | Cl {pcl_desc= Pcl_let ({pvbs_bindings; _}, _, _); _}, _
2244
+ when dont_parenze_exp_in_bindings pvbs_bindings exp ->
2245
+ false
2246
+ | Lb pvb , _ when parenze_exp_in_bindings [pvb] exp -> true
2247
+ | Exp {pexp_desc= Pexp_let ({pvbs_bindings; _}, _, _); _}, _
2248
+ | Cl {pcl_desc= Pcl_let ({pvbs_bindings; _}, _, _); _}, _
2249
+ when parenze_exp_in_bindings pvbs_bindings exp ->
2250
+ true
2251
+ | _, {pexp_desc= Pexp_infix _; pexp_attributes= _ :: _ ; _}
2252
+ when ctx_sensitive_to_trailing_attributes ctx ->
2253
+ true
2177
2254
| ( Str
2178
2255
{ pstr_desc=
2179
2256
Pstr_value
@@ -2260,32 +2337,32 @@ end = struct
2260
2337
when e == exp ->
2261
2338
true
2262
2339
| ( Exp {pexp_desc= Pexp_function (_, _, Pfunction_body e); _}
2263
- , {pexp_desc= Pexp_function (_, _ , Pfunction_cases _); _} )
2340
+ , {pexp_desc= Pexp_function ([] , None , Pfunction_cases _); _} )
2264
2341
when e == exp ->
2265
2342
true
2343
+ | ( Exp
2344
+ { pexp_desc=
2345
+ ( Pexp_extension
2346
+ ( _
2347
+ , PStr
2348
+ [ { pstr_desc=
2349
+ Pstr_eval
2350
+ ( { pexp_desc=
2351
+ ( Pexp_function
2352
+ (_, _, Pfunction_cases (cases, _, _))
2353
+ | Pexp_match (_, cases)
2354
+ | Pexp_try (_, cases) )
2355
+ ; _ }
2356
+ , _ )
2357
+ ; _ } ] )
2358
+ | Pexp_function (_, _, Pfunction_cases (cases, _, _))
2359
+ | Pexp_match (_, cases)
2360
+ | Pexp_try (_, cases) )
2361
+ ; _ }
2362
+ , _ ) ->
2363
+ parenze_exp_in_match_case cases exp
2266
2364
| Exp {pexp_desc; _} , _ -> (
2267
2365
match pexp_desc with
2268
- | Pexp_extension
2269
- ( _
2270
- , PStr
2271
- [ { pstr_desc=
2272
- Pstr_eval
2273
- ( { pexp_desc=
2274
- ( Pexp_function
2275
- (_, _, Pfunction_cases (cases, _, _))
2276
- | Pexp_match (_, cases)
2277
- | Pexp_try (_, cases) )
2278
- ; _ }
2279
- , _ )
2280
- ; _ } ] )
2281
- | Pexp_function (_, _, Pfunction_cases (cases, _, _))
2282
- | Pexp_match (_, cases)
2283
- | Pexp_try (_ , cases ) ->
2284
- if ! leading_nested_match_parens then
2285
- List. iter cases ~f: (fun {pc_rhs; _} ->
2286
- mark_parenzed_inner_nested_match pc_rhs ) ;
2287
- List. exists cases ~f: (fun {pc_rhs; _} -> pc_rhs == exp)
2288
- && exposed_right_exp Match exp
2289
2366
| Pexp_ifthenelse (eN, _)
2290
2367
when List. exists eN ~f: (fun x -> x.if_cond == exp) ->
2291
2368
false
@@ -2347,7 +2424,10 @@ end = struct
2347
2424
| _ -> Exp. has_trailing_attributes exp || parenze () ) )
2348
2425
| _ , {pexp_desc = Pexp_list _ ; _} -> false
2349
2426
| _ , {pexp_desc = Pexp_array _ ; _} -> false
2350
- | _ , exp when Exp. has_trailing_attributes exp -> true
2427
+ | _, exp
2428
+ when ctx_sensitive_to_trailing_attributes ctx
2429
+ && Exp. has_trailing_attributes exp ->
2430
+ true
2351
2431
| _ -> false
2352
2432
2353
2433
(* * [parenze_cl {ctx; ast}] holds when class expr [ast] should be
0 commit comments