Skip to content

Commit 97329f3

Browse files
objmagictrefis
authored andcommitted
Extend open to arbritrary module expressions in structures and to
applicative module paths in signatures
1 parent 6dc171e commit 97329f3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+5371
-4455
lines changed

.depend

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,15 @@ typing/includemod.cmo : typing/types.cmi typing/typedtree.cmi \
244244
typing/oprint.cmi typing/mtype.cmi utils/misc.cmi parsing/location.cmi \
245245
typing/includecore.cmi typing/includeclass.cmi typing/ident.cmi \
246246
typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi utils/clflags.cmi \
247-
parsing/builtin_attributes.cmi typing/btype.cmi typing/includemod.cmi
247+
parsing/builtin_attributes.cmi typing/btype.cmi parsing/asttypes.cmi \
248+
typing/includemod.cmi
248249
typing/includemod.cmx : typing/types.cmx typing/typedtree.cmx \
249250
typing/subst.cmx typing/printtyp.cmx typing/primitive.cmx typing/path.cmx \
250251
typing/oprint.cmx typing/mtype.cmx utils/misc.cmx parsing/location.cmx \
251252
typing/includecore.cmx typing/includeclass.cmx typing/ident.cmx \
252253
typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx utils/clflags.cmx \
253-
parsing/builtin_attributes.cmx typing/btype.cmx typing/includemod.cmi
254+
parsing/builtin_attributes.cmx typing/btype.cmx parsing/asttypes.cmi \
255+
typing/includemod.cmi
254256
typing/includemod.cmi : typing/types.cmi typing/typedtree.cmi \
255257
typing/path.cmi parsing/location.cmi typing/includecore.cmi \
256258
typing/ident.cmi typing/env.cmi typing/ctype.cmi
@@ -513,8 +515,7 @@ typing/typemod.cmx : utils/warnings.cmx typing/typetexp.cmx typing/types.cmx \
513515
typing/typemod.cmi : typing/types.cmi typing/typedtree.cmi \
514516
typing/typedecl.cmi typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \
515517
parsing/longident.cmi parsing/location.cmi typing/includemod.cmi \
516-
typing/ident.cmi typing/env.cmi typing/cmi_format.cmi \
517-
parsing/asttypes.cmi
518+
typing/ident.cmi typing/env.cmi typing/cmi_format.cmi
518519
typing/typeopt.cmo : typing/types.cmi typing/typedtree.cmi \
519520
typing/typedecl.cmi typing/predef.cmi typing/path.cmi bytecomp/lambda.cmi \
520521
typing/ident.cmi typing/env.cmi typing/ctype.cmi utils/config.cmi \

Changes

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ Working version
99
(Thomas Refis, with help and review from Alain Frisch, Gabriel Scherer, Jeremy
1010
Yallop, Leo White and Luc Maranget)
1111

12+
- GPR#1506, GPR#XXXX: Extended open to arbitrary module expression in
13+
structures and to applicative paths in signatures
14+
(Runhang Li, review by Alain Frisch, Florian Angeletti, Jeremy Yallop and
15+
Thomas Refis)
16+
1217
- GPR#1705: Allow @@attributes on exceptions.
1318
(Hugo Heuzard, review by Gabriel Radanne and Thomas Refis)
1419

boot/menhir/parser.ml

Lines changed: 4096 additions & 3828 deletions
Large diffs are not rendered by default.

bytecomp/translclass.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ let rec build_object_init cl_table obj params inh_init obj_init cl =
193193
build_object_init cl_table obj (vals @ params) inh_init obj_init cl
194194
in
195195
(inh_init, Translcore.transl_let rec_flag defs obj_init)
196-
| Tcl_open (_, _, _, _, cl)
196+
| Tcl_open (_, cl)
197197
| Tcl_constraint (cl, _, _, _, _) ->
198198
build_object_init cl_table obj params inh_init obj_init cl
199199

@@ -383,7 +383,7 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
383383
Lsequence(mkappl (oo_prim "narrow", narrow_args),
384384
cl_init))
385385
end
386-
| Tcl_open (_, _, _, _, cl) ->
386+
| Tcl_open (_, cl) ->
387387
build_class_init cla cstr super inh_init cl_init msubst top cl
388388

389389
let rec build_class_lets cl =
@@ -403,7 +403,7 @@ let rec get_class_meths cl =
403403
| Tcl_fun (_, _, _, cl, _)
404404
| Tcl_let (_, _, _, cl)
405405
| Tcl_apply (cl, _)
406-
| Tcl_open (_, _, _, _, cl)
406+
| Tcl_open (_, cl)
407407
| Tcl_constraint (cl, _, _, _, _) -> get_class_meths cl
408408

409409
(*
@@ -451,7 +451,7 @@ let rec transl_class_rebind obj_init cl vf =
451451
in
452452
check_constraint cl.cl_type;
453453
(path, path_lam, obj_init)
454-
| Tcl_open (_, _, _, _, cl) ->
454+
| Tcl_open (_, cl) ->
455455
transl_class_rebind obj_init cl vf
456456

457457
let rec transl_class_rebind_0 (self:Ident.t) obj_init cl vf =

bytecomp/translcore.ml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,32 @@ and transl_exp0 e =
538538
}
539539
| Texp_unreachable ->
540540
raise (Error (e.exp_loc, Unreachable_reached))
541+
| Texp_open (od, e) ->
542+
let pure = pure_module od.open_expr in
543+
(* this optimization shouldn't be needed because Simplif would
544+
actually remove the [Llet] when it's not used.
545+
But since [scan_used_globals] runs before Simplif, we need to
546+
do it. *)
547+
begin match od.open_bound_items with
548+
| [] when pure = Alias -> transl_exp e
549+
| _ ->
550+
let oid = Ident.create_local "open" in
551+
let body, _ =
552+
List.fold_left (fun (body, pos) id ->
553+
Llet(Alias, Pgenval, id,
554+
Lprim(Pfield pos, [Lvar oid], od.open_loc), body),
555+
pos + 1
556+
) (transl_exp e, 0) (bound_value_identifiers od.open_bound_items)
557+
in
558+
Llet(pure, Pgenval, oid,
559+
!transl_module Tcoerce_none None od.open_expr, body)
560+
end
561+
562+
and pure_module m =
563+
match m.mod_desc with
564+
Tmod_ident _ -> Alias
565+
| Tmod_constraint (m,_,_,_) -> pure_module m
566+
| _ -> Strict
541567

542568
and transl_list expr_list =
543569
List.map transl_exp expr_list

bytecomp/translcore.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ open Asttypes
2020
open Typedtree
2121
open Lambda
2222

23+
val pure_module : module_expr -> let_kind
24+
2325
val transl_exp: expression -> lambda
2426
val transl_apply: ?should_be_tailcall:bool
2527
-> ?inlined:inline_attribute

bytecomp/translmod.ml

Lines changed: 118 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ let init_shape id modl =
231231
and init_shape_struct env sg =
232232
match sg with
233233
[] -> []
234-
| Sig_value(subid, {val_kind=Val_reg; val_type=ty; val_loc=loc}) :: rem ->
234+
| Sig_value(subid, {val_kind=Val_reg; val_type=ty; val_loc=loc},_) :: rem ->
235235
let init_v =
236236
match Ctype.expand_head env ty with
237237
{desc = Tarrow(_,_,_,_)} ->
@@ -242,23 +242,23 @@ let init_shape id modl =
242242
let not_a_function = {reason=Unsafe_non_function; loc; subid } in
243243
raise (Initialization_failure not_a_function) in
244244
init_v :: init_shape_struct env rem
245-
| Sig_value(_, {val_kind=Val_prim _}) :: rem ->
245+
| Sig_value(_, {val_kind=Val_prim _}, _) :: rem ->
246246
init_shape_struct env rem
247247
| Sig_value _ :: _rem ->
248248
assert false
249-
| Sig_type(id, tdecl, _) :: rem ->
249+
| Sig_type(id, tdecl, _, _) :: rem ->
250250
init_shape_struct (Env.add_type ~check:false id tdecl env) rem
251-
| Sig_typext (subid, {ext_loc=loc},_) :: _ ->
251+
| Sig_typext (subid, {ext_loc=loc},_,_) :: _ ->
252252
raise (Initialization_failure {reason=Unsafe_typext; loc; subid})
253-
| Sig_module(id, Mp_present, md, _) :: rem ->
253+
| Sig_module(id, Mp_present, md, _, _) :: rem ->
254254
init_shape_mod id md.md_loc env md.md_type ::
255255
init_shape_struct (Env.add_module_declaration ~check:false
256256
id Mp_present md env) rem
257-
| Sig_module(id, Mp_absent, md, _) :: rem ->
257+
| Sig_module(id, Mp_absent, md, _, _) :: rem ->
258258
init_shape_struct
259259
(Env.add_module_declaration ~check:false
260260
id Mp_absent md env) rem
261-
| Sig_modtype(id, minfo) :: rem ->
261+
| Sig_modtype(id, minfo, _) :: rem ->
262262
init_shape_struct (Env.add_modtype id minfo env) rem
263263
| Sig_class _ :: rem ->
264264
Const_pointer 2 (* camlinternalMod.Class *)
@@ -376,22 +376,6 @@ let compile_recmodule compile_rhs bindings cont =
376376
bindings))
377377
cont
378378

379-
(* Extract the list of "value" identifiers bound by a signature.
380-
"Value" identifiers are identifiers for signature components that
381-
correspond to a run-time value: values, extensions, modules, classes.
382-
Note: manifest primitives do not correspond to a run-time value! *)
383-
384-
let rec bound_value_identifiers = function
385-
[] -> []
386-
| Sig_value(id, {val_kind = Val_reg}) :: rem ->
387-
id :: bound_value_identifiers rem
388-
| Sig_typext(id, _, _) :: rem -> id :: bound_value_identifiers rem
389-
| Sig_module(id, Mp_present, _, _) :: rem ->
390-
id :: bound_value_identifiers rem
391-
| Sig_class(id, _, _) :: rem -> id :: bound_value_identifiers rem
392-
| _ :: rem -> bound_value_identifiers rem
393-
394-
395379
(* Code to translate class entries in a structure *)
396380

397381
let transl_class_bindings cl_list =
@@ -673,18 +657,38 @@ and transl_structure loc fields cc rootpath final_env = function
673657
transl_module Tcoerce_none None modl, body),
674658
size
675659

660+
| Tstr_open od ->
661+
let pure = pure_module od.open_expr in
662+
(* this optimization shouldn't be needed because Simplif would
663+
actually remove the [Llet] when it's not used.
664+
But since [scan_used_globals] runs before Simplif, we need to do
665+
it. *)
666+
begin match od.open_bound_items with
667+
| [] when pure = Alias ->
668+
transl_structure loc fields cc rootpath final_env rem
669+
| _ ->
670+
let ids = bound_value_identifiers od.open_bound_items in
671+
let mid = Ident.create_local "open" in
672+
let rec rebind_idents pos newfields = function
673+
[] ->
674+
transl_structure loc newfields cc rootpath final_env rem
675+
| id :: ids ->
676+
let body, size =
677+
rebind_idents (pos + 1) (id :: newfields) ids
678+
in
679+
Llet(Alias, Pgenval, id,
680+
Lprim(Pfield pos, [Lvar mid], od.open_loc), body),
681+
size
682+
in
683+
let body, size = rebind_idents 0 fields ids in
684+
Llet(pure, Pgenval, mid,
685+
transl_module Tcoerce_none None od.open_expr, body), size
686+
end
676687
| Tstr_modtype _
677-
| Tstr_open _
678688
| Tstr_class_type _
679689
| Tstr_attribute _ ->
680690
transl_structure loc fields cc rootpath final_env rem
681691

682-
and pure_module m =
683-
match m.mod_desc with
684-
Tmod_ident _ -> Alias
685-
| Tmod_constraint (m,_,_,_) -> pure_module m
686-
| _ -> Strict
687-
688692
(* Update forward declaration in Translcore *)
689693
let _ =
690694
Translcore.transl_module := transl_module
@@ -771,7 +775,8 @@ let rec defined_idents = function
771775
| Tstr_recmodule decls ->
772776
List.map (fun mb -> mb.mb_id) decls @ defined_idents rem
773777
| Tstr_modtype _ -> defined_idents rem
774-
| Tstr_open _ -> defined_idents rem
778+
| Tstr_open od ->
779+
bound_value_identifiers od.open_bound_items @ defined_idents rem
775780
| Tstr_class cl_list ->
776781
List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ defined_idents rem
777782
| Tstr_class_type _ -> defined_idents rem
@@ -793,7 +798,12 @@ let rec more_idents = function
793798
| Tstr_exception _ -> more_idents rem
794799
| Tstr_recmodule _ -> more_idents rem
795800
| Tstr_modtype _ -> more_idents rem
796-
| Tstr_open _ -> more_idents rem
801+
| Tstr_open od ->
802+
let rest = more_idents rem in
803+
begin match od.open_expr.mod_desc with
804+
| Tmod_structure str -> all_idents str.str_items @ rest
805+
| _ -> rest
806+
end
797807
| Tstr_class _ -> more_idents rem
798808
| Tstr_class_type _ -> more_idents rem
799809
| Tstr_include{incl_mod={mod_desc =
@@ -827,7 +837,15 @@ and all_idents = function
827837
| Tstr_recmodule decls ->
828838
List.map (fun mb -> mb.mb_id) decls @ all_idents rem
829839
| Tstr_modtype _ -> all_idents rem
830-
| Tstr_open _ -> all_idents rem
840+
| Tstr_open od ->
841+
let rest = all_idents rem in
842+
begin match od.open_expr.mod_desc with
843+
| Tmod_structure str ->
844+
bound_value_identifiers od.open_bound_items
845+
@ all_idents str.str_items
846+
@ rest
847+
| _ -> bound_value_identifiers od.open_bound_items @ rest
848+
end
831849
| Tstr_class cl_list ->
832850
List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ all_idents rem
833851
| Tstr_class_type _ -> all_idents rem
@@ -1076,8 +1094,52 @@ let transl_store_structure glob map prims aliases str =
10761094
Lambda.subst no_env_update subst
10771095
(transl_module Tcoerce_none None modl),
10781096
store_idents 0 ids)
1097+
| Tstr_open od ->
1098+
begin match od.open_expr.mod_desc with
1099+
| Tmod_structure str ->
1100+
let lam =
1101+
transl_store rootpath subst lambda_unit str.str_items
1102+
in
1103+
let ids = Array.of_list (defined_idents str.str_items) in
1104+
let ids0 = bound_value_identifiers od.open_bound_items in
1105+
let subst = !transl_store_subst in
1106+
let rec store_idents pos = function
1107+
| [] -> transl_store rootpath subst cont rem
1108+
| id :: idl ->
1109+
Llet(Alias, Pgenval, id, Lvar ids.(pos),
1110+
Lsequence(store_ident od.open_loc id,
1111+
store_idents (pos + 1) idl))
1112+
in
1113+
Lsequence(lam, Lambda.subst no_env_update subst
1114+
(store_idents 0 ids0))
1115+
| _ ->
1116+
let pure = pure_module od.open_expr in
1117+
(* this optimization shouldn't be needed because Simplif would
1118+
actually remove the [Llet] when it's not used.
1119+
But since [scan_used_globals] runs before Simplif, we need to
1120+
do it. *)
1121+
match od.open_bound_items with
1122+
| [] when pure = Alias -> transl_store rootpath subst cont rem
1123+
| _ ->
1124+
let ids = bound_value_identifiers od.open_bound_items in
1125+
let mid = Ident.create_local "open" in
1126+
let loc = od.open_loc in
1127+
let rec store_idents pos = function
1128+
[] ->
1129+
transl_store rootpath (add_idents true ids subst) cont
1130+
rem
1131+
| id :: idl ->
1132+
Llet(Alias, Pgenval, id, Lprim(Pfield pos, [Lvar mid],
1133+
loc),
1134+
Lsequence(store_ident loc id,
1135+
store_idents (pos + 1) idl))
1136+
in
1137+
Llet(pure, Pgenval, mid,
1138+
Lambda.subst no_env_update subst
1139+
(transl_module Tcoerce_none None od.open_expr),
1140+
store_idents 0 ids)
1141+
end
10791142
| Tstr_modtype _
1080-
| Tstr_open _
10811143
| Tstr_class_type _
10821144
| Tstr_attribute _ ->
10831145
transl_store rootpath subst cont rem
@@ -1319,8 +1381,29 @@ let transl_toplevel_item item =
13191381
| Tstr_primitive descr ->
13201382
record_primitive descr.val_val;
13211383
lambda_unit
1384+
| Tstr_open od ->
1385+
let pure = pure_module od.open_expr in
1386+
(* this optimization shouldn't be needed because Simplif would
1387+
actually remove the [Llet] when it's not used.
1388+
But since [scan_used_globals] runs before Simplif, we need to do
1389+
it. *)
1390+
begin match od.open_bound_items with
1391+
| [] when pure = Alias -> lambda_unit
1392+
| _ ->
1393+
let ids = bound_value_identifiers od.open_bound_items in
1394+
let mid = Ident.create_local "open" in
1395+
let rec set_idents pos = function
1396+
[] ->
1397+
lambda_unit
1398+
| id :: ids ->
1399+
Lsequence(toploop_setvalue id
1400+
(Lprim(Pfield pos, [Lvar mid], Location.none)),
1401+
set_idents (pos + 1) ids)
1402+
in
1403+
Llet(pure, Pgenval, mid,
1404+
transl_module Tcoerce_none None od.open_expr, set_idents 0 ids)
1405+
end
13221406
| Tstr_modtype _
1323-
| Tstr_open _
13241407
| Tstr_module {mb_presence=Mp_absent}
13251408
| Tstr_type _
13261409
| Tstr_class_type _

0 commit comments

Comments
 (0)