Skip to content

Commit ef3c1df

Browse files
authored
Preserve functor concrete syntax in the Parsetree (ocaml-ppx#2345)
1 parent e0f668b commit ef3c1df

File tree

14 files changed

+150
-220
lines changed

14 files changed

+150
-220
lines changed

lib/Ast.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,7 +1350,7 @@ end = struct
13501350
|Pexp_field (e, _)
13511351
|Pexp_lazy e
13521352
|Pexp_letexception (_, e)
1353-
|Pexp_letmodule (_, _, e)
1353+
|Pexp_letmodule (_, _, _, e)
13541354
|Pexp_newtype (_, e)
13551355
|Pexp_open (_, e)
13561356
|Pexp_letopen (_, e)
@@ -1932,7 +1932,7 @@ end = struct
19321932
| Pexp_let (_, e)
19331933
|Pexp_letop {body= e; _}
19341934
|Pexp_letexception (_, e)
1935-
|Pexp_letmodule (_, _, e) -> (
1935+
|Pexp_letmodule (_, _, _, e) -> (
19361936
match cls with Match | Then | ThenElse -> continue e | _ -> false )
19371937
| Pexp_match _ when match cls with Then -> true | _ -> false ->
19381938
false
@@ -2000,7 +2000,7 @@ end = struct
20002000
| Pexp_let (_, e)
20012001
|Pexp_letop {body= e; _}
20022002
|Pexp_letexception (_, e)
2003-
|Pexp_letmodule (_, _, e) ->
2003+
|Pexp_letmodule (_, _, _, e) ->
20042004
continue e
20052005
| Pexp_ifthenelse (eN, None) -> continue (List.last_exn eN).if_body
20062006
| Pexp_extension (ext, PStr [{pstr_desc= Pstr_eval (e, _); _}])

lib/Extended_ast.ml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,42 @@ module Parse = struct
215215
{p with pexp_desc= Pexp_pack (name, Some pt)}
216216
| e -> Ast_mapper.default_mapper.expr m e
217217
in
218-
Ast_mapper.{default_mapper with expr; pat; binding_op}
218+
let module_expr (m : Ast_mapper.mapper) me =
219+
let me =
220+
match me with
221+
(* [functor () -> functor () -> E] => [functor () () -> E] *)
222+
| { pmod_desc=
223+
Pmod_functor
224+
( args
225+
, { pmod_desc= Pmod_functor (args', me')
226+
; pmod_attributes= []
227+
; _ } )
228+
; pmod_attributes= []
229+
; _ } ->
230+
{me with pmod_desc= Pmod_functor (args @ args', me')}
231+
| x -> x
232+
in
233+
Ast_mapper.default_mapper.module_expr m me
234+
in
235+
let module_type (m : Ast_mapper.mapper) mt =
236+
let mt =
237+
match mt with
238+
(* [functor () -> functor () -> E] => [functor () () -> E] *)
239+
| { pmty_desc=
240+
Pmty_functor
241+
( args
242+
, { pmty_desc= Pmty_functor (args', mt')
243+
; pmty_attributes= []
244+
; _ } )
245+
; pmty_attributes= []
246+
; _ } ->
247+
{mt with pmty_desc= Pmty_functor (args @ args', mt')}
248+
| x -> x
249+
in
250+
Ast_mapper.default_mapper.module_type m mt
251+
in
252+
Ast_mapper.
253+
{default_mapper with expr; pat; binding_op; module_expr; module_type}
219254

220255
let ast (type a) (fg : a t) ~preserve_beginend ~input_name str : a =
221256
map fg (normalize_mapper ~preserve_beginend)

lib/Fmt_ast.ml

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,6 @@ let box_fun_sig_args c =
158158
| `Fit_or_vertical -> hvbox
159159
| `Wrap | `Smart -> hovbox
160160

161-
let sugar_pmod_functor c ~for_functor_kw pmod =
162-
let source_is_long = Source.is_long_pmod_functor c.source in
163-
Sugar.functor_ c.cmts ~for_functor_kw ~source_is_long pmod
164-
165-
let sugar_pmty_functor c ~for_functor_kw pmty =
166-
let source_is_long = Source.is_long_pmty_functor c.source in
167-
Sugar.functor_type c.cmts ~for_functor_kw ~source_is_long pmty
168-
169161
let closing_paren ?force ?(offset = 0) c =
170162
match c.conf.fmt_opts.indicate_multiline_delimiters.v with
171163
| `No -> str ")"
@@ -2240,11 +2232,9 @@ and fmt_expression c ?(box = true) ?pro ?epi ?eol ?parens ?(indent_wrap = 0)
22402232
$ fmt "@;<1000 0>"
22412233
$ fmt_expression c (sub_exp ~ctx exp) )
22422234
$ fmt_atrs )
2243-
| Pexp_letmodule (name, pmod, exp) ->
2235+
| Pexp_letmodule (name, args, pmod, exp) ->
22442236
let keyword = "let module" in
2245-
let xargs, xbody =
2246-
sugar_pmod_functor c ~for_functor_kw:false (sub_mod ~ctx pmod)
2247-
in
2237+
let xbody = sub_mod ~ctx pmod in
22482238
let xbody, xmty =
22492239
match xbody.ast with
22502240
| { pmod_desc= Pmod_constraint (body_me, body_mt)
@@ -2265,7 +2255,7 @@ and fmt_expression c ?(box = true) ?pro ?epi ?eol ?parens ?(indent_wrap = 0)
22652255
(parens || not (List.is_empty pexp_attributes))
22662256
c.conf
22672257
( hvbox 2
2268-
(fmt_module c ctx keyword ~eqty:":" name xargs (Some xbody)
2258+
(fmt_module c ctx keyword ~eqty:":" name args (Some xbody)
22692259
xmty [] ~epi:(str "in") ~can_sparse ?ext ~rec_flag:false )
22702260
$ fmt "@;<1000 0>"
22712261
$ fmt_expression c (sub_exp ~ctx exp) )
@@ -3447,17 +3437,15 @@ and fmt_module_type c ?(rec_ = false) ({ast= mty; _} as xmty) =
34473437
Some
34483438
( str "end" $ after
34493439
$ fmt_attributes_and_docstrings c pmty_attributes ) }
3450-
| Pmty_functor _ ->
3451-
let for_functor_kw = true in
3452-
let xargs, mt2 = sugar_pmty_functor c ~for_functor_kw xmty in
3453-
let blk = fmt_module_type c mt2 in
3440+
| Pmty_functor (args, mt) ->
3441+
let blk = fmt_module_type c (sub_mty ~ctx mt) in
34543442
{ blk with
34553443
pro=
34563444
Some
34573445
( str "functor"
34583446
$ fmt_attributes c ~pre:Blank pmty_attributes
34593447
$ fmt "@;<1 2>"
3460-
$ list xargs "@;<1 2>" (fmt_functor_param c ctx)
3448+
$ list args "@;<1 2>" (fmt_functor_param c ctx)
34613449
$ fmt "@;<1 2>->"
34623450
$ opt blk.pro (fun pro -> str " " $ pro) )
34633451
; epi= Some (fmt_opt blk.epi $ Cmts.fmt_after c pmty_loc)
@@ -3767,22 +3755,19 @@ and fmt_module c ctx ?rec_ ?ext ?epi ?(can_sparse = false) keyword
37673755
and fmt_module_declaration ?ext c ~rec_flag ~first {ast= pmd; _} =
37683756
protect c (Md pmd)
37693757
@@
3770-
let {pmd_name; pmd_type; pmd_attributes; pmd_loc} = pmd in
3758+
let {pmd_name; pmd_args; pmd_type; pmd_attributes; pmd_loc} = pmd in
37713759
update_config_maybe_disabled c pmd_loc pmd_attributes
37723760
@@ fun c ->
37733761
let ctx = Md pmd in
37743762
let ext = if first then ext else None in
37753763
let keyword = if first then "module" else "and" in
3776-
let xargs, xmty =
3777-
if rec_flag then ([], sub_mty ~ctx pmd_type)
3778-
else sugar_pmty_functor c ~for_functor_kw:false (sub_mty ~ctx pmd_type)
3779-
in
3764+
let xmty = sub_mty ~ctx pmd_type in
37803765
let eqty =
37813766
match xmty.ast.pmty_desc with Pmty_alias _ -> None | _ -> Some ":"
37823767
in
37833768
Cmts.fmt c pmd_loc
3784-
(fmt_module ~rec_:rec_flag ?ext c ctx keyword pmd_name xargs None ?eqty
3785-
(Some xmty) ~rec_flag:(rec_flag && first) pmd_attributes )
3769+
(fmt_module ~rec_:rec_flag ?ext c ctx keyword pmd_name pmd_args None
3770+
?eqty (Some xmty) ~rec_flag:(rec_flag && first) pmd_attributes )
37863771

37873772
and fmt_module_substitution ?ext c ctx pms =
37883773
let {pms_name; pms_manifest; pms_attributes; pms_loc} = pms in
@@ -3995,8 +3980,7 @@ and fmt_module_expr ?(dock_struct = true) c ({ast= m; _} as xmod) =
39953980
Option.some_if has_epi
39963981
( Cmts.fmt_after c pmod_loc
39973982
$ fmt_attributes_and_docstrings c pmod_attributes ) }
3998-
| Pmod_functor _ ->
3999-
let xargs, me = sugar_pmod_functor c ~for_functor_kw:true xmod in
3983+
| Pmod_functor (args, me) ->
40003984
let doc, atrs = doc_atrs pmod_attributes in
40013985
{ empty with
40023986
bdy=
@@ -4007,10 +3991,11 @@ and fmt_module_expr ?(dock_struct = true) c ({ast= m; _} as xmod) =
40073991
( str "functor"
40083992
$ fmt_attributes c ~pre:Blank atrs
40093993
$ fmt "@;<1 2>"
4010-
$ list xargs "@;<1 2>" (fmt_functor_param c ctx)
3994+
$ list args "@;<1 2>" (fmt_functor_param c ctx)
40113995
$ fmt "@;<1 2>->@;<1 2>"
4012-
$ compose_module (fmt_module_expr c me) ~f:(hvbox 0) ) )
4013-
) }
3996+
$ compose_module
3997+
(fmt_module_expr c (sub_mod ~ctx me))
3998+
~f:(hvbox 0) ) ) ) }
40143999
| Pmod_ident lid ->
40154000
{ empty with
40164001
opn= Some (open_hvbox 2)
@@ -4337,9 +4322,7 @@ and fmt_module_binding ?ext c ~rec_flag ~first {ast= pmb; _} =
43374322
let ctx = Mb pmb in
43384323
let ext = if first then ext else None in
43394324
let keyword = if first then "module" else "and" in
4340-
let xargs, xbody =
4341-
sugar_pmod_functor c ~for_functor_kw:false (sub_mod ~ctx pmb.pmb_expr)
4342-
in
4325+
let xbody = sub_mod ~ctx pmb.pmb_expr in
43434326
let xbody, xmty =
43444327
match xbody.ast with
43454328
| { pmod_desc= Pmod_constraint (body_me, body_mt)
@@ -4352,7 +4335,7 @@ and fmt_module_binding ?ext c ~rec_flag ~first {ast= pmb; _} =
43524335
in
43534336
Cmts.fmt c pmb.pmb_loc
43544337
(fmt_module ~rec_:rec_flag ?ext c ctx keyword
4355-
~rec_flag:(rec_flag && first) ~eqty:":" pmb.pmb_name xargs
4338+
~rec_flag:(rec_flag && first) ~eqty:":" pmb.pmb_name pmb.pmb_args
43564339
(Some xbody) xmty pmb.pmb_attributes )
43574340

43584341
let fmt_toplevel_directive c ~semisemi dir =

lib/Source.ml

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -104,29 +104,6 @@ let extend_loc_to_include_attributes (loc : Location.t) (l : attributes) =
104104
else
105105
{loc with loc_end= {loc.loc_end with pos_cnum= loc_end.loc_end.pos_cnum}}
106106

107-
let is_long_functor_syntax (t : t) ~(from : Location.t) = function
108-
| Unit -> false
109-
| Named ({loc= _; _}, _) -> (
110-
(* since 4.12 the functor keyword is just before the loc of the functor
111-
parameter *)
112-
match
113-
find_token_before t
114-
~filter:(function COMMENT _ | DOCSTRING _ -> false | _ -> true)
115-
from.loc_start
116-
with
117-
| Some (Parser.FUNCTOR, _) -> true
118-
| _ -> false )
119-
120-
let is_long_pmod_functor t {pmod_desc; pmod_loc= from; _} =
121-
match pmod_desc with
122-
| Pmod_functor (fp, _) -> is_long_functor_syntax t ~from fp
123-
| _ -> false
124-
125-
let is_long_pmty_functor t {pmty_desc; pmty_loc= from; _} =
126-
match pmty_desc with
127-
| Pmty_functor (fp, _) -> is_long_functor_syntax t ~from fp
128-
| _ -> false
129-
130107
let string_literal t mode loc =
131108
Option.value_exn ~message:"Parse error while reading string literal"
132109
(Literal_lexer.string mode (string_at t loc))

lib/Source.mli

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,6 @@ val find_token_before :
4747

4848
val string_literal : t -> [`Normalize | `Preserve] -> Location.t -> string
4949

50-
val is_long_pmod_functor : t -> module_expr -> bool
51-
(** [is_long_pmod_functor source mod_exp] holds if [mod_exp] is a
52-
[Pmod_functor] expression that is expressed in long ('functor (M) ->')
53-
form in source. *)
54-
55-
val is_long_pmty_functor : t -> module_type -> bool
56-
(** [is_long_pmty_functor source mod_type] holds if [mod_type] is a
57-
[Pmty_functor] type that is expressed in long ('functor (M) ->') form in
58-
source. *)
59-
6050
val begins_line : ?ignore_spaces:bool -> t -> Location.t -> bool
6151

6252
val ends_line : t -> Location.t -> bool

lib/Sugar.ml

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -163,41 +163,6 @@ let sequence cmts xexp =
163163
in
164164
sequence_ xexp
165165

166-
(* The sugar is different when used with the [functor] keyword. The syntax
167-
M(A : A)(B : B) cannot handle [_] as module name. *)
168-
let rec functor_type cmts ~for_functor_kw ~source_is_long
169-
({ast= mty; _} as xmty) =
170-
let ctx = Mty mty in
171-
match mty with
172-
| {pmty_desc= Pmty_functor (fp, body); pmty_loc; pmty_attributes}
173-
when for_functor_kw
174-
|| (List.is_empty pmty_attributes && not (source_is_long mty)) ->
175-
let body = sub_mty ~ctx body in
176-
let xargs, xbody =
177-
match pmty_attributes with
178-
| [] -> functor_type cmts ~for_functor_kw ~source_is_long body
179-
| _ -> ([], body)
180-
in
181-
(Location.mkloc fp pmty_loc :: xargs, xbody)
182-
| _ -> ([], xmty)
183-
184-
(* The sugar is different when used with the [functor] keyword. The syntax
185-
M(A : A)(B : B) cannot handle [_] as module name. *)
186-
let rec functor_ cmts ~for_functor_kw ~source_is_long ({ast= me; _} as xme) =
187-
let ctx = Mod me in
188-
match me with
189-
| {pmod_desc= Pmod_functor (fp, body); pmod_loc; pmod_attributes}
190-
when for_functor_kw
191-
|| (List.is_empty pmod_attributes && not (source_is_long me)) ->
192-
let body = sub_mod ~ctx body in
193-
let xargs, xbody_me =
194-
match pmod_attributes with
195-
| [] -> functor_ cmts ~for_functor_kw ~source_is_long body
196-
| _ -> ([], body)
197-
in
198-
(Location.mkloc fp pmod_loc :: xargs, xbody_me)
199-
| _ -> ([], xme)
200-
201166
let mod_with pmty =
202167
let rec mod_with_ ({ast= me; _} as xme) =
203168
let ctx = Mty me in

lib/Sugar.mli

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,6 @@ val sequence :
5151
(** [sequence cmts exp] returns the list of expressions (with the optional
5252
extension) from a sequence of expressions [exp]. *)
5353

54-
val functor_type :
55-
Cmts.t
56-
-> for_functor_kw:bool
57-
-> source_is_long:(module_type -> bool)
58-
-> module_type Ast.xt
59-
-> functor_parameter loc list * module_type Ast.xt
60-
(** [functor_type cmts for_functor_kw m] returns the list of module types
61-
applied to the functor of module type [m]. [for_functor_kw] indicates if
62-
the keyword [functor] is used. *)
63-
64-
val functor_ :
65-
Cmts.t
66-
-> for_functor_kw:bool
67-
-> source_is_long:(module_expr -> bool)
68-
-> module_expr Ast.xt
69-
-> functor_parameter loc list * module_expr Ast.xt
70-
(** [functor_ cmts for_functor_kw m] returns the list of module types applied
71-
to the functor of module [m]. [for_functor_kw] indicates if the keyword
72-
[functor] is used. *)
73-
7454
val mod_with :
7555
module_type Ast.xt
7656
-> (with_constraint list * Warnings.loc * attributes) list

test/passing/tests/comments.ml.ref

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,7 @@ let y =
320320
(* b *)
321321
x
322322

323-
module A (* A *) () =
324-
(* B *)
325-
(* C *)
326-
B
323+
module A (* A *) () (* B *) = (* C *) B
327324

328325
let kk = (* foo *) (module A : T)
329326

vendor/parser-extended/ast_helper.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ module Exp = struct
145145
let indexop_access ?loc ?attrs pia_lhs pia_kind pia_paren pia_rhs =
146146
mk ?loc ?attrs (Pexp_indexop_access {pia_lhs; pia_kind; pia_paren; pia_rhs})
147147
let override ?loc ?attrs a = mk ?loc ?attrs (Pexp_override a)
148-
let letmodule ?loc ?attrs a b c= mk ?loc ?attrs (Pexp_letmodule (a, b, c))
148+
let letmodule ?loc ?attrs a b c d = mk ?loc ?attrs (Pexp_letmodule (a, b, c, d))
149149
let letexception ?loc ?attrs a b = mk ?loc ?attrs (Pexp_letexception (a, b))
150150
let assert_ ?loc ?attrs a = mk ?loc ?attrs (Pexp_assert a)
151151
let lazy_ ?loc ?attrs a = mk ?loc ?attrs (Pexp_lazy a)
@@ -367,9 +367,10 @@ end
367367

368368
module Md = struct
369369
let mk ?(loc = !default_loc) ?(attrs = [])
370-
?(docs = empty_docs) ?(text = []) name typ =
370+
?(docs = empty_docs) ?(text = []) name args typ =
371371
{
372372
pmd_name = name;
373+
pmd_args = args;
373374
pmd_type = typ;
374375
pmd_attributes =
375376
add_text_attrs text (add_docs_attrs docs attrs);
@@ -403,9 +404,10 @@ end
403404

404405
module Mb = struct
405406
let mk ?(loc = !default_loc) ?(attrs = [])
406-
?(docs = empty_docs) ?(text = []) name expr =
407+
?(docs = empty_docs) ?(text = []) name args expr =
407408
{
408409
pmb_name = name;
410+
pmb_args = args;
409411
pmb_expr = expr;
410412
pmb_attributes =
411413
add_text_attrs text (add_docs_attrs docs attrs);

0 commit comments

Comments
 (0)