Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/Ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1585,7 +1585,7 @@ end = struct
|Pexp_unboxed_field (e, _)
|Pexp_lazy e
|Pexp_letexception (_, e)
|Pexp_letmodule (_, _, _, e)
|Pexp_letmodule (_, _, _, _, e)
|Pexp_newtype (_, e)
|Pexp_open (_, e)
|Pexp_letopen (_, e)
Expand Down Expand Up @@ -2291,7 +2291,7 @@ end = struct
| Pexp_let (_, e)
|Pexp_letop {body= e; _}
|Pexp_letexception (_, e)
|Pexp_letmodule (_, _, _, e) -> (
|Pexp_letmodule (_, _, _, _, e) -> (
match cls with Match | Then | ThenElse -> continue e | _ -> false )
| Pexp_match _ when match cls with Then -> true | _ -> false ->
false
Expand Down Expand Up @@ -2370,7 +2370,7 @@ end = struct
| Pexp_let (_, e)
|Pexp_letop {body= e; _}
|Pexp_letexception (_, e)
|Pexp_letmodule (_, _, _, e) ->
|Pexp_letmodule (_, _, _, _, e) ->
continue e
| Pexp_ifthenelse (eN, None) -> continue (List.last_exn eN).if_body
| Pexp_extension (ext, PStr [{pstr_desc= Pstr_eval (e, _); _}])
Expand Down Expand Up @@ -2461,7 +2461,7 @@ end = struct
| Exp {pexp_desc; _} -> (
match pexp_desc with
| Pexp_let (_, e)
|Pexp_letmodule (_, _, _, e)
|Pexp_letmodule (_, _, _, _, e)
|Pexp_letexception (_, e)
|Pexp_letopen (_, e)
|Pexp_open (_, e)
Expand Down
2 changes: 1 addition & 1 deletion lib/Exposed.ml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ module Right_square = struct
| Pexp_ifthenelse (_, Some exp) -> expression exp
| Pexp_sequence (_, exp) -> expression exp
| Pexp_setinstvar (_, exp) -> expression exp
| Pexp_letmodule (_, _, _, exp) -> expression exp
| Pexp_letmodule (_, _, _, _, exp) -> expression exp
| Pexp_letexception (_, exp) -> expression exp
| Pexp_assert exp -> expression exp
| Pexp_lazy exp -> expression exp
Expand Down
101 changes: 43 additions & 58 deletions lib/Fmt_ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,28 @@ let let_binding_can_be_punned ~binding ~is_ext =
true
| _ -> false

let extract_module_binding_constraints c ctx modes body =
let xbody = sub_mod ~ctx body in
let xbody, xmty, xmodes =
match xbody.ast with
| { pmod_desc= Pmod_constraint (body_me, body_mt, body_mm)
; pmod_loc
; pmod_attributes= [] } ->
let xbody = sub_mod ~ctx body_me in
let xmty, after =
match body_mt with
| None -> (None, body_me.pmod_loc)
| Some body_mt -> (Some (sub_mty ~ctx body_mt), body_mt.pmty_loc)
in
Cmts.relocate c.cmts ~src:pmod_loc ~before:body_me.pmod_loc ~after ;
(xbody, xmty, body_mm)
| _ -> (xbody, None, [])
in
(* [xmodes_id] is the modes on the identifier, while [xmodes] is the modes
on the RHS. For example, [module (F @ xmodes_id) () @ xmodes = ...]. *)
let xmodes_id = modes in
(xmodes_id, xmty, xmodes, xbody)

let rec fmt_extension_aux c ctx ~key (ext, pld) =
match (ext.txt, pld, ctx) with
(* Quoted extensions (since ocaml 4.11). *)
Expand Down Expand Up @@ -2839,25 +2861,10 @@ and fmt_expression c ?(box = true) ?(pro = noop) ?eol ?parens
$ fmt "@;<1000 0>"
$ fmt_expression c (sub_exp ~ctx exp) )
$ fmt_atrs )
| Pexp_letmodule (name, args, pmod, exp) ->
| Pexp_letmodule (name, modes, args, pmod, exp) ->
let keyword = "let module" in
let xbody = sub_mod ~ctx pmod in
let xbody, xmty, xmmodes =
match xbody.ast with
| { pmod_desc= Pmod_constraint (body_me, body_mt, body_mm)
; pmod_loc
; pmod_attributes= [] } ->
let xbody = sub_mod ~ctx body_me in
let xmty, after =
match body_mt with
| None -> (None, body_me.pmod_loc)
| Some body_mt ->
(Some (sub_mty ~ctx body_mt), body_mt.pmty_loc)
in
Cmts.relocate c.cmts ~src:pmod_loc ~before:body_me.pmod_loc
~after ;
(xbody, xmty, body_mm)
| _ -> (xbody, None, [])
let xmodes_id, xmty, xmodes, xbody =
extract_module_binding_constraints c ctx modes pmod
in
let can_sparse =
match xbody.ast.pmod_desc with
Expand All @@ -2870,8 +2877,8 @@ and fmt_expression c ?(box = true) ?(pro = noop) ?eol ?parens
(parens || not (List.is_empty pexp_attributes))
c.conf
( hvbox 2
(fmt_module c ctx keyword ~eqty:":" name (Modes xmmodes)
args (Some xbody) xmty
(fmt_module c ctx keyword ~eqty:":" name (Modes xmodes_id)
args (Some xbody) xmty (Modes xmodes)
~attrs:(Ast_helper.Attr.ext_attrs ?ext ())
~epi:(str "in") ~can_sparse ~rec_flag:false )
$ fmt "@;<1000 0>"
Expand Down Expand Up @@ -4569,7 +4576,7 @@ and fmt_class_exprs ?ext c ctx cls =
@@ Cmts.fmt c cl.pci_loc (doc_before $ class_exprs $ doc_after) )

and fmt_module c ctx ?rec_ ?epi ?(can_sparse = false) keyword ?(eqty = "=")
name modals xargs xbody xmty ~attrs ~rec_flag =
name modals_id xargs xbody xmty modals ~attrs ~rec_flag =
let ext = attrs.attrs_extension in
let blk_t =
Option.value_map xmty ~default:empty ~f:(fun xmty ->
Expand All @@ -4579,20 +4586,11 @@ and fmt_module c ctx ?rec_ ?epi ?(can_sparse = false) keyword ?(eqty = "=")
Some (str " " $ str eqty $ opt blk.pro (fun pro -> str " " $ pro))
; psp= fmt_if (Option.is_none blk.pro) "@;<1 2>" $ blk.psp } )
in
let fmt_name, fmt_trailing_modals =
match modals with
| Modes _ ->
(* [module M : S @ m = M] *)
(fmt_str_loc_opt c name, fmt_modals c modals)
| Modalities _ ->
(* [module (M @@ m) : S] *)
( wrap_if
(not (is_empty_modals modals))
"(" ")"
(fmt_str_loc_opt c name $ fmt_modals c modals)
, noop )
| No_modals -> (fmt_str_loc_opt c name, noop)
| Mode_crossing _ -> assert false
let fmt_name =
wrap_if
(not (is_empty_modals modals_id))
"(" ")"
(fmt_str_loc_opt c name $ fmt_modals c modals_id)
in
let blk_b = Option.value_map xbody ~default:empty ~f:(fmt_module_expr c) in
let fmt_name_and_mt ~pro ~loc name mt =
Expand Down Expand Up @@ -4656,7 +4654,7 @@ and fmt_module c ctx ?rec_ ?epi ?(can_sparse = false) keyword ?(eqty = "=")
( hvbox args_p.indent
(fmt_args ~pro:intro xargs $ fmt_opt blk_t.pro)
$ blk_t.psp $ blk_t.bdy )
$ blk_t.esp $ fmt_opt blk_t.epi $ fmt_trailing_modals
$ blk_t.esp $ fmt_opt blk_t.epi $ fmt_modals c modals
$ fmt_if (Option.is_some xbody) " ="
$ fmt_if_k compact fmt_pro )
$ fmt_if_k (not compact) fmt_pro
Expand Down Expand Up @@ -4697,7 +4695,7 @@ and fmt_module_declaration c ~rec_flag ~first {ast= pmd; _} =
in
Cmts.fmt c pmd_loc
(fmt_module ~rec_:rec_flag c ctx keyword pmd_name
(Modalities pmd_modalities) pmd_args None ?eqty (Some xmty)
(Modalities pmd_modalities) pmd_args None ?eqty (Some xmty) No_modals
~rec_flag:(rec_flag && first) ~attrs )

and fmt_module_substitution c ctx pms =
Expand All @@ -4714,7 +4712,7 @@ and fmt_module_substitution c ctx pms =
let pms_name = {pms_name with txt= Some pms_name.txt} in
Cmts.fmt c pms_loc
(fmt_module c ctx "module" ~eqty:":=" pms_name No_modals [] None
(Some xmty) ~attrs ~rec_flag:false )
(Some xmty) No_modals ~attrs ~rec_flag:false )

and fmt_module_type_declaration ?eqty c ctx pmtd =
let {pmtd_name; pmtd_type; pmtd_ext_attrs= attrs; pmtd_loc} = pmtd in
Expand All @@ -4724,7 +4722,7 @@ and fmt_module_type_declaration ?eqty c ctx pmtd =
fmt_module ?eqty c ctx "module type" pmtd_name No_modals [] None
~rec_flag:false
(Option.map pmtd_type ~f:(sub_mty ~ctx))
~attrs
No_modals ~attrs

and fmt_open_description ?ext c ?(keyword = "open") ~kw_attributes
{popen_expr= popen_lid; popen_override; popen_attributes; popen_loc} =
Expand Down Expand Up @@ -4787,14 +4785,14 @@ and fmt_with_constraint c ctx ~pre = function
let m2 = Some (sub_mty ~ctx m2) in
str pre $ break 1 2
$ fmt_module c ctx "module type" m1 No_modals [] None ~rec_flag:false
m2
m2 No_modals
~attrs:(Ast_helper.Attr.ext_attrs ())
| Pwith_modtypesubst (m1, m2) ->
let m1 = {m1 with txt= Some (str_longident m1.txt)} in
let m2 = Some (sub_mty ~ctx m2) in
str pre $ break 1 2
$ fmt_module c ctx ~eqty:":=" "module type" m1 No_modals [] None
~rec_flag:false m2
~rec_flag:false m2 No_modals
~attrs:(Ast_helper.Attr.ext_attrs ())

and fmt_mod_apply c ctx loc attrs ~parens ~dock_struct me_f arg =
Expand Down Expand Up @@ -5361,26 +5359,13 @@ and fmt_module_binding c ~rec_flag ~first {ast= pmb; _} =
@@ fun c ->
let ctx = Mb pmb in
let keyword = if first then "module" else "and" in
let xbody = sub_mod ~ctx pmb.pmb_expr in
let xbody, xmty, xmodes =
match xbody.ast with
| { pmod_desc= Pmod_constraint (body_me, body_mt, body_mm)
; pmod_loc
; pmod_attributes= [] } ->
let xbody = sub_mod ~ctx body_me in
let xmty, after =
match body_mt with
| None -> (None, body_me.pmod_loc)
| Some body_mt -> (Some (sub_mty ~ctx body_mt), body_mt.pmty_loc)
in
Cmts.relocate c.cmts ~src:pmod_loc ~before:body_me.pmod_loc ~after ;
(xbody, xmty, body_mm)
| _ -> (xbody, None, [])
let xmodes_id, xmty, xmodes, xbody =
extract_module_binding_constraints c ctx pmb.pmb_modes pmb.pmb_expr
in
Cmts.fmt c pmb.pmb_loc
(fmt_module ~rec_:rec_flag c ctx keyword ~rec_flag:(rec_flag && first)
~eqty:":" pmb_name (Modes xmodes) pmb.pmb_args (Some xbody) xmty
~attrs )
~eqty:":" pmb_name (Modes xmodes_id) pmb.pmb_args (Some xbody) xmty
(Modes xmodes) ~attrs )

let fmt_toplevel_directive c ~semisemi dir =
let fmt_dir_arg = function
Expand Down
97 changes: 97 additions & 0 deletions test/passing/tests/module_modes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,100 @@ let () =
let () =
let module (* 38 *) M (* 39 *) @ (* 40 *) m (* 41 *) = (* 42 *) M (* 43 *) in
()

(* test mode on ident *)

module (M @ foo) = struct end

module (M @ foo) : S = struct end

(* No functor args: [bar] should move onto [M] *)

module (M @ foo) @ bar = struct end

module (M @ foo) : S @ bar = struct end

module (F @ foo) () = struct end

module (F @ foo) () : S = struct end

(* There are functor args: [bar] is not allowed to move *)

module (F @ foo) () @ bar = struct end

module (F @ foo) () : S @ bar = struct end

module rec (M @ foo) : S @ bar = struct end
and (N @ foo) : S @ bar = struct end

module rec (F @ foo) () : S @ bar = struct end
and (G @ foo) () : S @ bar = struct end

(* attributes *)

module[@a] (M @ foo) = struct end

module[@a] (M @ foo) : S = struct end

module[@a] (M @ foo) @ bar = struct end

module[@a] (M @ foo) : S @ bar = struct end

module[@a] (F @ foo) () = struct end

module[@a] (F @ foo) () : S = struct end

module[@a] (F @ foo) () @ bar = struct end

module[@a] (F @ foo) () : S @ bar = struct end

module rec (M @ foo) = (struct end : S @ bar) [@a]
and (N @ foo) = (struct end : S @ bar) [@a]

module rec (F @ foo) () = (struct end : S @ bar) [@a]
and (G @ foo) () = (struct end : S @ bar) [@a]

module rec (M @ foo) : S @ bar = (struct end [@a])
and (N @ foo) : S @ bar = (struct end [@a])

module rec (F @ foo) () : S @ bar = (struct end [@a])
and (G @ foo) () : S @ bar = (struct end [@a])

let () =
let module (M @ foo) = struct end in ()

let () =
let module (M @ foo) : S = struct end in ()

let () =
let module (M @ foo) @ bar = struct end in ()

let () =
let module (M @ foo) : S @ bar = struct end in ()

let () =
let module (F @ foo) () = struct end in ()

let () =
let module (F @ foo) () : S = struct end in ()

let () =
let module (F @ foo) () @ bar = struct end in ()

let () =
let module (F @ foo) () : S @ bar = struct end in ()

(* comments *)

module rec (* 44 *) ( (* 45 *) F (* 46 *) @ (* 47 *) foo (* 48 *)) (* 49 *) () (* 50 *)
: (* 51 *) S (* 52 *) @ (* 53 *) bar (* 54 *) = (* 55 *) (struct (* 55 *) end (* 56 *)
[@a]) (* 57 *)
and (* 58 *) (G (* 59 *) @ (* 60 *) foo (* 61 *)) (* 62 *) () (* 63 *)
: (* 64 *) S (* 65 *) @ (* 66 *) bar (* 67 *) = (* 68 *) (struct (* 69 *) end (* 70 *)
[@a]) (* 71 *)

module (* 72 *) ( (* 73 *) M (* 74 *) @ (* 75 *) foo (* 76 *)) (* 77 *) @ (* 78 *) bar
(* 79 *) = (* 80 *) struct (* 81 *) end (* 82 *)

module (* 83 *) ( (* 84 *) M (* 85 *) @ (* 86 *) foo (* 87 *)) (* 88 *)
: (* 89 *) S (* 90 *) @ (* 91 *) bar (* 92 *) = (* 93 *) struct (* 94 *) end (* 95 *)
Loading