Skip to content

Commit 678b590

Browse files
authored
Add -parameter parameter (#1846)
Squashed from `parameter-parameter` branch on lukemaurer/flambda-backend (commit 81c50a7). Declares that the module being compiled has a parameter, whose type is given by an .mli. Given `-parameter Param`, we require that: * An interface `param.mli` is in the path and was compiled with `-as-parameter` * All subsequent modules that refer to this module will also be compiled with `-parameter Param` Once support for parameterised libraries is complete, it will also be possible for a reference to pass an argument rather than forwarding `Param` along.
1 parent bee63ee commit 678b590

31 files changed

+458
-41
lines changed

ocaml/driver/main_args.ml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,14 +654,19 @@ let mk_match_context_rows f =
654654
Printf.sprintf
655655
"<n> (advanced, see manual section %d.%d.)" chapter section
656656

657+
let mk_parameter f =
658+
"-parameter", Arg.String f,
659+
"<module name> Compile the module with <module name> as a parameter."
660+
;;
661+
657662
let mk_as_parameter f =
658663
"-as-parameter", Arg.Unit f,
659-
" Compiles the interface as a parameter for an open module."
664+
" Compile the interface as a parameter module."
660665
;;
661666

662667
let mk_as_argument_for f =
663668
"-as-argument-for", Arg.String f,
664-
"<module name> Compiles the module as an argument for the named parameter."
669+
"<module name> Compile the module as an argument for the named parameter."
665670
;;
666671

667672
let mk_use_prims f =
@@ -1001,6 +1006,7 @@ module type Compiler_options = sig
10011006
val _output_obj : unit -> unit
10021007
val _output_complete_obj : unit -> unit
10031008
val _pack : unit -> unit
1009+
val _parameter : string -> unit
10041010
val _plugin : string -> unit
10051011
val _pp : string -> unit
10061012
val _principal : unit -> unit
@@ -1236,6 +1242,7 @@ struct
12361242
mk_output_complete_obj F._output_complete_obj;
12371243
mk_output_complete_exe F._output_complete_exe;
12381244
mk_pack_byt F._pack;
1245+
mk_parameter F._parameter;
12391246
mk_pp F._pp;
12401247
mk_ppx F._ppx;
12411248
mk_plugin F._plugin;
@@ -1473,6 +1480,7 @@ struct
14731480
mk_output_complete_obj F._output_complete_obj;
14741481
mk_p F._p;
14751482
mk_pack_opt F._pack;
1483+
mk_parameter F._parameter;
14761484
mk_plugin F._plugin;
14771485
mk_pp F._pp;
14781486
mk_ppx F._ppx;
@@ -2012,6 +2020,7 @@ module Default = struct
20122020
let _o s = output_name := (Some s)
20132021
let _opaque = set opaque
20142022
let _pack = set make_package
2023+
let _parameter s = parameters := !parameters @ [ s ]
20152024
let _plugin _p = plugin := true
20162025
let _pp s = preprocessor := (Some s)
20172026
let _runtime_variant s = runtime_variant := s

ocaml/driver/main_args.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ module type Compiler_options = sig
119119
val _output_obj : unit -> unit
120120
val _output_complete_obj : unit -> unit
121121
val _pack : unit -> unit
122+
val _parameter : string -> unit
122123
val _plugin : string -> unit
123124
val _pp : string -> unit
124125
val _principal : unit -> unit

ocaml/file_formats/cmi_format.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,14 @@ type header = {
6464
header_name : Compilation_unit.Name.t;
6565
header_kind : kind;
6666
header_sign : Serialized.signature;
67+
header_params : Compilation_unit.Name.t list;
6768
}
6869

6970
type 'sg cmi_infos_generic = {
7071
cmi_name : Compilation_unit.Name.t;
7172
cmi_kind : kind;
7273
cmi_sign : 'sg;
74+
cmi_params : Compilation_unit.Name.t list;
7375
cmi_crcs : crcs;
7476
cmi_flags : flags;
7577
}
@@ -124,13 +126,15 @@ let input_cmi_lazy ic =
124126
header_name = name;
125127
header_kind = kind;
126128
header_sign = sign;
129+
header_params = params;
127130
} = (input_value ic : header) in
128131
let crcs = (input_value ic : crcs) in
129132
let flags = (input_value ic : flags) in
130133
{
131134
cmi_name = name;
132135
cmi_kind = kind;
133136
cmi_sign = deserialize data sign;
137+
cmi_params = params;
134138
cmi_crcs = crcs;
135139
cmi_flags = flags;
136140
}
@@ -191,6 +195,7 @@ let output_cmi filename oc cmi =
191195
header_name = cmi.cmi_name;
192196
header_kind = cmi.cmi_kind;
193197
header_sign = sign;
198+
header_params = cmi.cmi_params;
194199
};
195200
(* BACKPORT END *)
196201
flush oc;

ocaml/file_formats/cmi_format.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ type pers_flags =
2323
type kind =
2424
| Normal of {
2525
cmi_impl : Compilation_unit.t;
26+
(* If this module takes parameters, [cmi_impl] will be the functor that
27+
generates instances *)
2628
cmi_arg_for : Compilation_unit.Name.t option;
2729
}
2830
| Parameter
@@ -31,6 +33,7 @@ type 'sg cmi_infos_generic = {
3133
cmi_name : Compilation_unit.Name.t;
3234
cmi_kind : kind;
3335
cmi_sign : 'sg;
36+
cmi_params : Compilation_unit.Name.t list;
3437
cmi_crcs : Import_info.t array;
3538
cmi_flags : pers_flags list;
3639
}

ocaml/lambda/translmod.ml

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1547,12 +1547,41 @@ let transl_implementation_set_fields compilation_unit (str, restr) =
15471547
compilation_unit;
15481548
required_globals = required_globals ~flambda:true code }
15491549

1550-
let transl_implementation compilation_unit impl ~style =
1550+
let transl_implementation0 compilation_unit impl ~style =
15511551
match style with
15521552
| Plain_block -> transl_implementation_plain_block compilation_unit impl
15531553
| Set_global_to_block -> transl_implementation_set_global compilation_unit impl
15541554
| Set_individual_fields -> transl_implementation_set_fields compilation_unit impl
15551555

1556+
let stub_out_runtime_parameters compilation_unit code =
1557+
let runtime_parameters = Env.runtime_parameters () in
1558+
match runtime_parameters with
1559+
| [] -> code
1560+
| _ ->
1561+
(* Raise [Invalid_argument "-parameter not yet implemented"] at top level. This
1562+
makes the module unusable (which is to say, safe) but well-formed so that
1563+
compilation goes through. *)
1564+
let scopes = enter_compilation_unit ~scopes:empty_scopes compilation_unit in
1565+
let loc = of_location ~scopes Location.none in
1566+
let slot =
1567+
transl_extension_path
1568+
loc
1569+
(Lazy.force Env.initial)
1570+
Predef.path_invalid_argument
1571+
in
1572+
let message =
1573+
Lconst (Const_base (Const_string("-parameter not yet implemented",
1574+
Location.none, None)))
1575+
in
1576+
Lprim (Praise Raise_regular,
1577+
[Lprim(Pmakeblock(0, Immutable, None, alloc_heap), [ slot; message ], loc)],
1578+
loc)
1579+
1580+
let transl_implementation compilation_unit impl ~style =
1581+
let program = transl_implementation0 compilation_unit impl ~style in
1582+
let code = stub_out_runtime_parameters compilation_unit program.code in
1583+
{ program with code }
1584+
15561585
(* Compile a toplevel phrase *)
15571586

15581587
let toploop_unit = Compilation_unit.of_string "Toploop"

ocaml/testsuite/tests/self-contained-toplevel/main.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,20 @@ let () =
2626
Persistent_signature.load := (fun ~allow_hidden ~unit_name ->
2727
match unit_name |> Compilation_unit.Name.to_string with
2828
| "Foo" ->
29-
let {Cmi_format.cmi_name; cmi_kind; cmi_sign; cmi_crcs; cmi_flags} =
29+
let
30+
{ Cmi_format.cmi_name;
31+
cmi_kind;
32+
cmi_params;
33+
cmi_sign;
34+
cmi_crcs;
35+
cmi_flags
36+
} =
3037
Marshal.from_string Cached_cmi.foo 0
3138
in
3239
let cmi =
3340
{ Cmi_format.cmi_name;
3441
cmi_kind;
42+
cmi_params;
3543
cmi_sign = Subst.Lazy.of_signature cmi_sign;
3644
cmi_crcs;
3745
cmi_flags
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(* TEST
2+
readonly_files = "bad_param_not_param.reference widget.mli";
3+
setup-ocamlc.byte-build-env;
4+
flags = "";
5+
module = "widget.mli";
6+
compiler_output = "bad_param_not_param.output";
7+
ocamlc_byte_exit_status = "0";
8+
ocamlc.byte;
9+
flags = "-parameter Widget";
10+
module = "bad_param_not_param.mli";
11+
ocamlc_byte_exit_status = "2";
12+
ocamlc.byte;
13+
compiler_reference = "bad_param_not_param.reference";
14+
check-ocamlc.byte-output;
15+
*)
16+
17+
(* Compiled with [-parameter Widget] but [Widget] is not a parameter *)
18+
19+
val frobnicate : Widget.t -> Widget.t
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
File "bad_param_not_param.mli", line 1:
2+
Error: The module Widget is specified as a parameter, but widget.cmi
3+
was not compiled with -as-parameter.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(* Compiled with both [-parameter Monoid] and [-as-parameter] *)
2+
3+
val f : Monoid.t -> Monoid.t
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
File "_none_", line 1:
2+
Error: Cannot combine -as-parameter with -parameter: parameters cannot
3+
be parameterised.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
File "bad_ref_indirect.ml", line 1:
2+
Error: The module Monoid_utils is not accessible because it takes Monoid
3+
as a parameter and the current unit does not.
4+
Hint: Pass `-parameter Monoid` to add Monoid as a parameter
5+
of the current unit.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type ts = Monoid.t list
2+
3+
let concat = List.fold_left Monoid.append Monoid.empty
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type ts = Monoid.t list
2+
3+
val concat : ts -> Monoid.t
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fatal error: exception Invalid_argument("-parameter not yet implemented")
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
File ref_indirect.cmo
2+
Unit name: Ref_indirect
3+
Interfaces imported:
4+
00000000000000000000000000000000 Stdlib
5+
00000000000000000000000000000000 Ref_indirect
6+
00000000000000000000000000000000 Monoid_utils
7+
00000000000000000000000000000000 Monoid
8+
00000000000000000000000000000000 CamlinternalFormatBasics
9+
Required globals:
10+
Uses unsafe features: no
11+
Force link: no
12+
File ref_indirect.cmi
13+
Unit name: Ref_indirect
14+
Is parameter: no
15+
Parameters:
16+
Monoid
17+
Interfaces imported:
18+
00000000000000000000000000000000 Ref_indirect
19+
00000000000000000000000000000000 Stdlib
20+
00000000000000000000000000000000 Monoid_utils
21+
00000000000000000000000000000000 Monoid
22+
00000000000000000000000000000000 CamlinternalFormatBasics
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
File ref_indirect.cmx
2+
Name: Ref_indirect
3+
CRC of implementation: 00000000000000000000000000000000
4+
Globals defined:
5+
Ref_indirect
6+
Interfaces imported:
7+
00000000000000000000000000000000 Stdlib
8+
00000000000000000000000000000000 Ref_indirect
9+
00000000000000000000000000000000 Monoid_utils
10+
00000000000000000000000000000000 Monoid
11+
00000000000000000000000000000000 CamlinternalFormatBasics
12+
Implementations imported:
13+
Flambda 2 unit (with no export information)
14+
Currying functions:
15+
Apply functions:
16+
Send functions:
17+
Force link: no
18+
Function summaries for static checks:
19+
camlRef_indirect__entry = 0x15
20+
File ref_indirect.cmi
21+
Unit name: Ref_indirect
22+
Is parameter: no
23+
Parameters:
24+
Monoid
25+
Interfaces imported:
26+
00000000000000000000000000000000 Ref_indirect
27+
00000000000000000000000000000000 Stdlib
28+
00000000000000000000000000000000 Monoid_utils
29+
00000000000000000000000000000000 Monoid
30+
00000000000000000000000000000000 CamlinternalFormatBasics
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let concat = Monoid_utils.concat

0 commit comments

Comments
 (0)