Skip to content

Commit

Permalink
feat: support module%ppx syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
anmonteiro committed Jul 28, 2024
1 parent a8a9ca2 commit aec9517
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 56 deletions.
54 changes: 38 additions & 16 deletions src/reason-parser/reason_parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -1664,15 +1664,16 @@ structure:
;

opt_LET_MODULE_ident:
| opt_LET_MODULE as_loc(mod_ident) { $2 }
| opt_LET_MODULE as_loc(LIDENT)
{ syntax_error $2.loc lowercase_module_msg; { $2 with txt = Some $2.txt } }
| opt_LET_MODULE item_extension_sugar as_loc(mod_ident) { Some $2, $3 }
| opt_LET_MODULE as_loc(mod_ident) { None, $2 }
| opt_LET_MODULE item_extension_sugar? as_loc(LIDENT)
{ syntax_error $3.loc lowercase_module_msg; $2, { $3 with txt = Some $3.txt } }
;

opt_LET_MODULE_REC_ident:
| opt_LET_MODULE REC as_loc(mod_ident) { $3 }
| opt_LET_MODULE REC as_loc(LIDENT)
{ syntax_error $3.loc lowercase_module_msg; { $3 with txt = Some $3.txt } }
| opt_LET_MODULE item_extension_sugar? REC as_loc(mod_ident) { $2, $4 }
| opt_LET_MODULE item_extension_sugar? REC as_loc(LIDENT)
{ syntax_error $4.loc lowercase_module_msg; $2, { $4 with txt = Some $4.txt } }
;

structure_item:
Expand Down Expand Up @@ -1708,11 +1709,17 @@ structure_item:
{ mkstr(Pstr_exception (Ast_helper.Te.mk_exception ~loc:$1.pext_loc $1)) }
| item_attributes opt_LET_MODULE_ident module_binding_body
{ let loc = mklocation $symbolstartpos $endpos in
mkstr(Pstr_module (Ast_helper.Mb.mk $2 $3 ~attrs:$1 ~loc)) }
let ext, letmod = $2 in
wrap_str_ext
~loc
(mkstr(Pstr_module (Ast_helper.Mb.mk letmod $3 ~attrs:$1 ~loc)))
ext
}
| item_attributes opt_LET_MODULE_REC_ident module_binding_body
and_module_bindings*
{ let loc = mklocation $symbolstartpos $endpos($2) in
mkstr (Pstr_recmodule ((Ast_helper.Mb.mk $2 $3 ~attrs:$1 ~loc) :: $4))
let _ext, letmodule = $2 in
mkstr (Pstr_recmodule ((Ast_helper.Mb.mk letmodule $3 ~attrs:$1 ~loc) :: $4))
}
| item_attributes MODULE TYPE OF? as_loc(ident)
{ let loc = mklocation $symbolstartpos $endpos in
Expand Down Expand Up @@ -1931,25 +1938,33 @@ signature_item:
{ Psig_exception $1 }
| item_attributes opt_LET_MODULE_ident module_declaration
{ let loc = mklocation $symbolstartpos $endpos in
Psig_module (Ast_helper.Md.mk $2 $3 ~attrs:$1 ~loc)
let ext, letmod = $2 in
wrap_sig_ext
~loc
(Psig_module (Ast_helper.Md.mk letmod $3 ~attrs:$1 ~loc))
ext
}
| item_attributes opt_LET_MODULE_ident EQUAL as_loc(mod_longident)
{ let loc = mklocation $symbolstartpos $endpos in
let loc_mod = mklocation $startpos($4) $endpos($4) in
Psig_module (
Ast_helper.Md.mk
$2
let ext, letmod = $2 in
wrap_sig_ext
~loc
(Psig_module
(Ast_helper.Md.mk
letmod
(Ast_helper.Mty.alias ~loc:loc_mod $4)
~attrs:$1
~loc
)
~loc))
ext
}
| item_attributes opt_LET_MODULE as_loc(UIDENT) COLONEQUAL as_loc(mod_ext_longident)
{ Psig_modsubst (Ast_helper.Ms.mk $3 $5 ~attrs:$1 ~loc:(mklocation $symbolstartpos $endpos))}
| item_attributes opt_LET_MODULE_REC_ident module_type_body(COLON)
and_module_rec_declaration*
{ let loc = mklocation $symbolstartpos $endpos($3) in
Psig_recmodule (Ast_helper.Md.mk $2 $3 ~attrs:$1 ~loc :: $4) }
let _ext, letmodule = $2 in
Psig_recmodule (Ast_helper.Md.mk letmodule $3 ~attrs:$1 ~loc :: $4) }
| item_attributes MODULE TYPE as_loc(ident)
{ let loc = mklocation $symbolstartpos $endpos in
Psig_modtype (Ast_helper.Mtd.mk $4 ~attrs:$1 ~loc)
Expand Down Expand Up @@ -2536,7 +2551,14 @@ mark_position_exp
seq_expr_no_seq [@recover.expr default_expr ()] (semi):
| expr semi { $1 }
| opt_LET_MODULE_ident module_binding_body SEMI seq_expr(SEMI?)
{ mkexp (Pexp_letmodule($1, $2, $4)) }
{ let loc = mklocation $symbolstartpos $endpos in
let ext, letmod = $1 in
let exp = mkexp (Pexp_letmodule(letmod, $2, $4)) in
match ext with
| None -> exp
| Some (ext_attrs, ext_id) ->
mkexp ~loc (Pexp_extension (ext_id, PStr [mkstrexp exp ext_attrs]))
}
| item_attributes LET? OPEN override_flag as_loc(mod_longident) SEMI seq_expr(SEMI?)
{ let loc = (mklocation $startpos($1) $endpos($4)) in
let me = Ast_helper.Mod.ident ~loc $5 in
Expand Down
79 changes: 39 additions & 40 deletions src/reason-parser/reason_pprint_ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ let expression_immediate_extension_sugar x =
| Some (name, expr) ->
match expr.pexp_desc with
| Pexp_for _ | Pexp_while _ | Pexp_ifthenelse _ | Pexp_function _
| Pexp_newtype _ | Pexp_try _ | Pexp_match _ ->
| Pexp_newtype _ | Pexp_try _ | Pexp_match _ (* | Pexp_letmodule _ *) ->
(Some name, expr)
| _ -> (None, x)

Expand Down Expand Up @@ -7204,6 +7204,7 @@ let printer = object(self:'self)
`let%private a = 1` *)
| Psig_value ({ pval_prim = [_]; _ } as vd) -> self#primitive_declaration ~extension vd
| Psig_value vd -> self#val_binding ~extension vd
| Psig_module pmd -> self#psig_module ~extension pmd
| _ -> self#payload "%%" extension (PSig [item])
end
| _ -> self#signature_item' item
Expand All @@ -7225,6 +7226,36 @@ let printer = object(self:'self)
~layout
()
method psig_module ?extension pmd =
let layout =
let prefix = add_extension_sugar "module" extension in
match pmd.pmd_type.pmty_desc with
| Pmty_alias alias ->
label ~space:true
(makeList ~postSpace:true [
atom prefix;
atom (moduleIdent pmd.pmd_name);
atom "="
])
(self#longident_loc alias)
| _ ->
let letPattern =
makeList
[makeList ~postSpace:true [atom prefix; (atom (moduleIdent pmd.pmd_name))];
atom ":"]
in
(self#module_type letPattern pmd.pmd_type)
in
let {stdAttrs; docAttrs} =
partitionAttributes ~partDoc:true pmd.pmd_attributes
in
self#attachDocAttrsToLayout
~stdAttrs
~docAttrs
~loc:pmd.pmd_name.loc
~layout:(self#attach_std_item_attrs stdAttrs @@ layout)
()
method signature_item' x : Layout.t =
let item: Layout.t =
match x.psig_desc with
Expand Down Expand Up @@ -7272,45 +7303,7 @@ let printer = object(self:'self)
(class_description ~class_keyword:true x)::
(List.map class_description xs)
)
| Psig_module {pmd_name; pmd_type={pmty_desc=Pmty_alias alias}; pmd_attributes} ->
let {stdAttrs; docAttrs} =
partitionAttributes ~partDoc:true pmd_attributes
in
let layout =
self#attach_std_item_attrs stdAttrs @@
label ~space:true
(makeList ~postSpace:true [
atom "module";
atom (moduleIdent pmd_name);
atom "="
])
(self#longident_loc alias)
in
self#attachDocAttrsToLayout
~stdAttrs
~docAttrs
~loc:pmd_name.loc
~layout
()
| Psig_module pmd ->
let {stdAttrs; docAttrs} =
partitionAttributes ~partDoc:true pmd.pmd_attributes
in
let letPattern =
makeList
[makeList ~postSpace:true [atom "module"; (atom (moduleIdent pmd.pmd_name))];
atom ":"]
in
let layout =
self#attach_std_item_attrs stdAttrs @@
(self#module_type letPattern pmd.pmd_type)
in
self#attachDocAttrsToLayout
~stdAttrs
~docAttrs
~loc:pmd.pmd_name.loc
~layout
()
| Psig_module pmd -> self#psig_module pmd
| Psig_open od ->
let {stdAttrs; docAttrs} =
partitionAttributes ~partDoc:true od.popen_attributes
Expand Down Expand Up @@ -7629,6 +7622,12 @@ let printer = object(self:'self)
`let%private a = 1` *)
| Pstr_value (rf, vb_list) -> self#bindings ~extension (rf, vb_list)
| Pstr_primitive vd -> self#primitive_declaration ~extension vd
| Pstr_module binding ->
let bindingName = atom ~loc:binding.pmb_name.loc (moduleIdent binding.pmb_name) in
let module_binding =
let prefix = add_extension_sugar "module" (Some extension) in
self#let_module_binding prefix bindingName binding.pmb_expr in
self#attach_std_item_attrs binding.pmb_attributes module_binding
| _ -> self#attach_std_item_attrs attrs (self#payload "%%" extension (PStr [item]))
end
| _ -> self#structure_item item
Expand Down
4 changes: 4 additions & 0 deletions test/general-syntax-rei.t/input.rei
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ external%foo bar: string => string = "";
[%%foo: let foo: bar];
let%foo foo: bar;

module%foo X: Y;

module%foo X = Y;

4 changes: 4 additions & 0 deletions test/general-syntax-rei.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ Format general interface syntax

let%foo foo: bar;
let%foo foo: bar;

module%foo X: Y;

module%foo X = Y;
17 changes: 17 additions & 0 deletions test/modules.t/input.re
Original file line number Diff line number Diff line change
Expand Up @@ -523,3 +523,20 @@ module type TypeWithExternalExtension = {
external%foo bar: string => string = "";
[%%foo: external bar: int => int = "hello" ];
}

module%foo X = Y

module%foo X = {
let x = 1;
};

let x = {
let module%foo X = {
let x = 1;
};
()
};

module%foo rec X: Y = {
let x = 1;
}

0 comments on commit aec9517

Please sign in to comment.