@@ -812,6 +812,8 @@ module rec In_ctx : sig
812812 val sub_sig : ctx :T .t -> signature_item -> signature_item xt
813813
814814 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
815817end = struct
816818 open Requires_sub_terms
817819
@@ -846,6 +848,8 @@ end = struct
846848 let sub_sig ~ctx sig_ = {ctx; ast= sig_}
847849
848850 let sub_str ~ctx str = {ctx; ast= str}
851+
852+ let sub_fun_body ~ctx ast = {ctx; ast}
849853end
850854
851855(* * Operations determining precedence and necessary parenthesization of terms
@@ -1202,9 +1206,15 @@ end = struct
12021206 | Ppat_constraint (p , _ ) -> p == pat
12031207 | _ -> false
12041208 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
12071216 in
1217+ let check_bindings l = List. exists l ~f: check_binding in
12081218 let check_param_val (_ , _ , p ) = p == pat in
12091219 let check_expr_function_param param =
12101220 match param.pparam_desc with
@@ -1217,7 +1227,6 @@ end = struct
12171227 let check_class_function_params =
12181228 List. exists ~f: check_class_function_param
12191229 in
1220- let check_cases = List. exists ~f: (fun c -> c.pc_lhs == pat) in
12211230 match ctx with
12221231 | Pld (PPat (p1 , _ )) -> assert (p1 == pat)
12231232 | Pld _ -> assert false
@@ -1283,7 +1292,7 @@ end = struct
12831292 | Fpe ctx -> assert (check_expr_function_param ctx)
12841293 | Fpc ctx -> assert (check_class_function_param ctx)
12851294 | Vc _ -> assert false
1286- | Lb x -> assert (x.pvb_pat == pat )
1295+ | Lb x -> assert (check_binding x )
12871296 | Bo x -> assert (x.pbop_pat == pat)
12881297 | Mb _ -> assert false
12891298 | Md _ -> assert false
@@ -1351,6 +1360,10 @@ end = struct
13511360 | {pc_rhs; _} when pc_rhs == exp -> true
13521361 | _ -> false )
13531362 in
1363+ let check_fun_body = function
1364+ | Pfunction_body body -> body == exp
1365+ | Pfunction_cases (cases , _ , _ ) -> check_cases cases
1366+ in
13541367 match ctx with
13551368 | Pld (PPat (_ , Some e1 )) -> assert (e1 == exp)
13561369 | Pld _ -> assert false
@@ -1365,8 +1378,8 @@ end = struct
13651378 | Pexp_object _ -> assert false
13661379 | Pexp_let ({pvbs_bindings; _} , e , _ ) ->
13671380 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 )
13701383 || e == exp )
13711384 | Pexp_letop {let_; ands; body; loc_in = _ } ->
13721385 let f {pbop_exp; _} = pbop_exp == exp in
@@ -1375,13 +1388,9 @@ end = struct
13751388 | Pexp_match (_ , cases ) | Pexp_try (_ , cases ) ->
13761389 assert (check_cases cases)
13771390 | 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
13831391 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 )
13851394 | Pexp_indexop_access {pia_lhs; pia_kind = Builtin idx ; pia_rhs; _} ->
13861395 assert (
13871396 pia_lhs == exp || idx == exp
@@ -1431,7 +1440,7 @@ end = struct
14311440 | Fpe ctx -> assert (check_expr_function_param ctx)
14321441 | Fpc ctx -> assert (check_class_function_param ctx)
14331442 | Vc _ -> assert false
1434- | Lb x -> assert (x.pvb_expr == exp )
1443+ | Lb x -> assert (check_fun_body x.pvb_body )
14351444 | Bo x -> assert (x.pbop_exp == exp)
14361445 | Mb _ -> assert false
14371446 | Md _ -> assert false
@@ -1440,8 +1449,8 @@ end = struct
14401449 | Pstr_eval (e0 , _ ) -> assert (e0 == exp)
14411450 | Pstr_value {pvbs_bindings; _} ->
14421451 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 ) )
14451454 | Pstr_extension ((_ , ext ), _ ) -> assert (check_extensions ext)
14461455 | Pstr_primitive _ | Pstr_type _ | Pstr_typext _ | Pstr_exception _
14471456 | Pstr_module _ | Pstr_recmodule _ | Pstr_modtype _ | Pstr_open _
@@ -1457,8 +1466,8 @@ end = struct
14571466 | Pcl_structure _ -> false
14581467 | Pcl_apply (_ , l ) -> List. exists l ~f: (fun (_ , e ) -> e == exp)
14591468 | 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 )
14621471 | Pcl_constraint _ -> false
14631472 | Pcl_extension _ -> false
14641473 | Pcl_open _ -> false
@@ -1866,6 +1875,23 @@ end = struct
18661875 | Ppat_tuple _ -> true
18671876 | _ -> false
18681877
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+
18691895 (* * [parenze_pat {ctx; ast}] holds when pattern [ast] should be
18701896 parenthesized in context [ctx]. *)
18711897 let parenze_pat ({ctx; ast = pat } as xpat ) =
@@ -1902,6 +1928,11 @@ end = struct
19021928 | Ppat_or _ | Ppat_alias _ ) ) ->
19031929 true
19041930 | 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
19051936 | _, Ppat_constraint _
19061937 | _, Ppat_unpack _
19071938 | ( Pat
@@ -1931,18 +1962,14 @@ end = struct
19311962 | Pat {ppat_desc= Ppat_tuple _; _}, Ppat_tuple _
19321963 | Pat _, Ppat_lazy _
19331964 | Pat _, Ppat_exception _
1934- | Exp {pexp_desc= Pexp_function (_, _, Pfunction_body _); _}, Ppat_or _
19351965 | Cl {pcl_desc= Pcl_fun _; _}, Ppat_variant (_, Some _)
19361966 | Cl {pcl_desc= Pcl_fun _; _}, Ppat_tuple _
19371967 | Cl {pcl_desc= Pcl_fun _; _}, Ppat_construct _
19381968 | Cl {pcl_desc= Pcl_fun _; _}, Ppat_alias _
19391969 | 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 _ ->
19441971 true
1945- | (Str _ | Exp _ ), Ppat_lazy _ -> true
1972+ | (Str _ | Exp _ | Lb _ ), Ppat_lazy _ -> true
19461973 | ( (Fpe _ | Fpc _)
19471974 , ( Ppat_tuple _ | Ppat_construct _ | Ppat_alias _ | Ppat_variant _
19481975 | Ppat_lazy _ | Ppat_exception _ | Ppat_or _ ) )
@@ -1953,23 +1980,36 @@ end = struct
19531980 | _ , Ppat_var _ when List. is_empty pat.ppat_attributes -> false
19541981 | ( ( Exp {pexp_desc= Pexp_let ({pvbs_bindings; _}, _, _); _}
19551982 | 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
19711996 | _ -> false
19721997
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+
19732013 let marked_parenzed_inner_nested_match =
19742014 let memo = Hashtbl.Poly. create () in
19752015 register_reset (fun () -> Hashtbl. clear memo) ;
@@ -2119,6 +2159,31 @@ end = struct
21192159 ~default: exposed_
21202160 |> (ignore : bool -> _ )
21212161
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+
21222187 (* * [parenze_exp {ctx; ast}] holds when expression [ast] should be
21232188 parenthesized in context [ctx]. *)
21242189 and parenze_exp ({ctx; ast = exp } as xexp ) =
@@ -2173,7 +2238,19 @@ end = struct
21732238 ||
21742239 match (ctx, exp) with
21752240 | 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
21772254 | ( Str
21782255 { pstr_desc=
21792256 Pstr_value
@@ -2260,32 +2337,32 @@ end = struct
22602337 when e == exp ->
22612338 true
22622339 | ( Exp {pexp_desc= Pexp_function (_, _, Pfunction_body e); _}
2263- , {pexp_desc= Pexp_function (_, _ , Pfunction_cases _); _} )
2340+ , {pexp_desc= Pexp_function ([] , None , Pfunction_cases _); _} )
22642341 when e == exp ->
22652342 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
22662364 | Exp {pexp_desc; _} , _ -> (
22672365 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
22892366 | Pexp_ifthenelse (eN, _)
22902367 when List. exists eN ~f: (fun x -> x.if_cond == exp) ->
22912368 false
@@ -2347,7 +2424,10 @@ end = struct
23472424 | _ -> Exp. has_trailing_attributes exp || parenze () ) )
23482425 | _ , {pexp_desc = Pexp_list _ ; _} -> false
23492426 | _ , {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
23512431 | _ -> false
23522432
23532433 (* * [parenze_cl {ctx; ast}] holds when class expr [ast] should be
0 commit comments