Skip to content

Commit c8b1102

Browse files
committed
feat(oxcaml): instantiate parameterized libraries
Signed-off-by: ArthurW <[email protected]>
1 parent 7861fb5 commit c8b1102

29 files changed

+1941
-113
lines changed

bin/describe/describe_external_lib_deps.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ let resolve_lib_deps db lib_deps =
9797
let open Memo.O in
9898
Memo.parallel_map lib_deps ~f:(fun (lib : Lib_dep.t) ->
9999
match lib with
100-
| Direct (_, name) | Re_export (_, name) ->
100+
| Direct (_, name) | Re_export (_, name) | Instantiate { lib = name; _ } ->
101101
let+ v = resolve_lib db name Kind.Required in
102102
[ v ]
103103
| Select select ->

src/dune_lang/lib_dep.ml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ type t =
9898
| Direct of (Loc.t * Lib_name.t)
9999
| Re_export of (Loc.t * Lib_name.t)
100100
| Select of Select.t
101+
| Instantiate of
102+
{ loc : Loc.t
103+
; lib : Lib_name.t
104+
; arguments : (Loc.t * Lib_name.t) list
105+
; new_name : Module_name.t option
106+
}
101107

102108
let equal = Poly.equal
103109

@@ -107,6 +113,13 @@ let to_dyn =
107113
| Direct (_, name) -> Lib_name.to_dyn name
108114
| Re_export (_, name) -> variant "re_export" [ Lib_name.to_dyn name ]
109115
| Select s -> variant "select" [ Select.to_dyn s ]
116+
| Instantiate { lib; arguments; new_name; loc = _ } ->
117+
variant
118+
"instantiate"
119+
[ Lib_name.to_dyn lib
120+
; list (fun (_, arg) -> Lib_name.to_dyn arg) arguments
121+
; option Module_name.to_dyn new_name
122+
]
110123
;;
111124

112125
let direct x = Direct x
@@ -126,6 +139,19 @@ let decode ~allow_re_export =
126139
, let+ select = Select.decode in
127140
Select select )
128141
]
142+
<|> enter
143+
((* TODO art-w: oxcaml extension is not recognized by installed
144+
libraries, which are missing a `(using oxcaml 0.1)`
145+
let+ () = Syntax.since Oxcaml.syntax (0, 1) *)
146+
let+ () = Syntax.since Stanza.syntax (3, 20)
147+
and+ loc, lib = located Lib_name.decode
148+
and+ arguments, new_name =
149+
until_keyword
150+
":as"
151+
~before:(located Lib_name.decode)
152+
~after:Module_name.decode
153+
in
154+
Instantiate { loc; lib; arguments; new_name })
129155
<|> let+ loc, name = located Lib_name.decode in
130156
Direct (loc, name))
131157
in
@@ -144,11 +170,22 @@ let encode =
144170
Code_error.raise
145171
"Lib_dep.encode: cannot encode select"
146172
[ "select", Select.to_dyn select ]
173+
| Instantiate { lib; arguments; new_name; loc = _ } ->
174+
let as_name =
175+
match new_name with
176+
| None -> []
177+
| Some new_name -> [ string ":as"; Module_name.encode new_name ]
178+
in
179+
list
180+
sexp
181+
((Lib_name.encode lib :: List.map arguments ~f:(fun (_, arg) -> Lib_name.encode arg))
182+
@ as_name)
147183
;;
148184

149185
module L = struct
150186
type kind =
151187
| Required
188+
| Required_multiple
152189
| Optional
153190
| Forbidden
154191

@@ -186,12 +223,21 @@ module L = struct
186223
[ Pp.textf
187224
"library %S is present both as a forbidden and required dependency"
188225
(Lib_name.to_string name)
226+
]
227+
| Required_multiple, Required_multiple -> acc
228+
| Required_multiple, _ | _, Required_multiple ->
229+
User_error.raise
230+
~loc
231+
[ Pp.textf
232+
"parameterized library %S is present in multiple forms"
233+
(Lib_name.to_string name)
189234
])
190235
in
191236
ignore
192237
(List.fold_left t ~init:Lib_name.Map.empty ~f:(fun acc x ->
193238
match x with
194239
| Re_export (_, s) | Direct (_, s) -> add Required s acc
240+
| Instantiate { lib = s; _ } -> add Required_multiple s acc
195241
| Select { choices; _ } ->
196242
List.fold_left choices ~init:acc ~f:(fun acc (c : Select.Choice.t) ->
197243
let acc = Lib_name.Set.fold c.required ~init:acc ~f:(add Optional) in

src/dune_lang/lib_dep.mli

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ type t =
2222
| Direct of (Loc.t * Lib_name.t)
2323
| Re_export of (Loc.t * Lib_name.t)
2424
| Select of Select.t
25+
| Instantiate of
26+
{ loc : Loc.t
27+
; lib : Lib_name.t
28+
; arguments : (Loc.t * Lib_name.t) list
29+
; new_name : Module_name.t option
30+
}
2531

2632
val equal : t -> t -> bool
2733
val to_dyn : t -> Dyn.t

src/dune_rules/compilation_context.ml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ type t =
8989
; requires_link : Lib.t list Resolve.t Memo.Lazy.t
9090
; implements : Virtual_rules.t
9191
; parameters : Module_name.t list Resolve.Memo.t
92+
; instances : Lib.Parameterized.instance list Resolve.Memo.t
9293
; includes : Includes.t
9394
; preprocessing : Pp_spec.t
9495
; opaque : bool
@@ -162,6 +163,7 @@ let create
162163
?modes
163164
?bin_annot
164165
?loc
166+
?instances
165167
()
166168
=
167169
let project = Scope.project scope in
@@ -187,6 +189,11 @@ let create
187189
| None -> Resolve.Memo.return []
188190
| Some parameters -> parameters_main_modules parameters
189191
in
192+
let instances =
193+
match instances with
194+
| None -> Resolve.Memo.return []
195+
| Some instances -> instances
196+
in
190197
let sandbox = Sandbox_config.no_special_requirements in
191198
let modes =
192199
let default =
@@ -236,6 +243,7 @@ let create
236243
; bin_annot
237244
; loc
238245
; ocaml
246+
; instances
239247
}
240248
;;
241249

@@ -244,7 +252,7 @@ let alias_and_root_module_flags =
244252
fun base -> Ocaml_flags.append_common base extra
245253
;;
246254

247-
let for_alias_module t alias_module =
255+
let for_alias_module ~has_instances t alias_module =
248256
let keep_flags = Modules.With_vlib.is_stdlib_alias (modules t) alias_module in
249257
let flags =
250258
if keep_flags
@@ -256,6 +264,15 @@ let for_alias_module t alias_module =
256264
let profile = Super_context.context t.super_context |> Context.profile in
257265
Ocaml_flags.default ~dune_version ~profile)
258266
in
267+
let flags =
268+
if has_instances
269+
then
270+
(* If the alias file instantiates parameterized libraries,
271+
the [misplace-attribute] warning is currently raised on
272+
[@jane.non_erasable.instances] *)
273+
Ocaml_flags.append_common flags [ "-w"; "-53" ]
274+
else flags
275+
in
259276
let sandbox =
260277
(* If the compiler reads the cmi for module alias even with [-w -49
261278
-no-alias-deps], we must sandbox the build of the alias module since the
@@ -342,3 +359,4 @@ let for_plugin_executable t ~embed_in_plugin_libraries =
342359
let without_bin_annot t = { t with bin_annot = false }
343360
let set_obj_dir t obj_dir = { t with obj_dir }
344361
let set_modes t ~modes = { t with modes }
362+
let instances t = t.instances

src/dune_rules/compilation_context.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ val create
3838
-> ?modes:Mode_conf.Set.Details.t Lib_mode.Map.t
3939
-> ?bin_annot:bool
4040
-> ?loc:Loc.t
41+
-> ?instances:Lib.Parameterized.instance list Resolve.Memo.t
4142
-> unit
4243
-> t Memo.t
4344

4445
(** Return a compilation context suitable for compiling the alias module. *)
45-
val for_alias_module : t -> Module.t -> t
46+
val for_alias_module : has_instances:bool -> t -> Module.t -> t
4647

4748
val super_context : t -> Super_context.t
4849
val context : t -> Context.t
@@ -90,3 +91,4 @@ val dep_graphs : t -> Dep_graph.t Ml_kind.Dict.t
9091
val loc : t -> Loc.t option
9192
val set_obj_dir : t -> Path.Build.t Obj_dir.t -> t
9293
val set_modes : t -> modes:Lib_mode.Map.Set.t -> t
94+
val instances : t -> Lib.Parameterized.instance list Resolve.Memo.t

src/dune_rules/dir_contents.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ end = struct
129129
dependencies *)
130130
List.filter_map libraries ~f:(fun dep ->
131131
match (dep : Lib_dep.t) with
132-
| Re_export _ | Direct _ -> None
132+
| Re_export _ | Direct _ | Instantiate _ -> None
133133
| Select s -> Some s.result_fn)
134134
;;
135135

src/dune_rules/dune_package.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ module Lib = struct
254254
| Public (_, _) -> Lib_info.Status.Installed
255255
in
256256
let version = None in
257+
let local_main_module_name = main_module_name in
257258
let main_module_name = Lib_info.Inherited.This main_module_name in
258259
let foreign_objects = Lib_info.Source.External foreign_objects in
259260
let public_headers = Lib_info.File_deps.External public_headers in
@@ -281,6 +282,7 @@ module Lib = struct
281282
~version
282283
~synopsis
283284
~main_module_name
285+
~local_main_module_name
284286
~sub_systems
285287
~requires
286288
~parameters

src/dune_rules/exe_rules.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ let executables_rules
184184
let* cctx =
185185
let requires_compile = Lib.Compile.direct_requires compile_info in
186186
let requires_link = Lib.Compile.requires_link compile_info in
187+
let instances = Lib.Compile.instances compile_info in
187188
let js_of_ocaml =
188189
Js_of_ocaml.Mode.Pair.mapi js_of_ocaml ~f:(fun mode x ->
189190
Option.some_if
@@ -205,6 +206,7 @@ let executables_rules
205206
~opaque:Inherit_from_settings
206207
~melange_package_name:None
207208
~package:exes.package
209+
~instances
208210
in
209211
let lib_config = ocaml.lib_config in
210212
let* requires_compile = Compilation_context.requires_compile cctx in

src/dune_rules/findlib.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ let to_dune_library (t : Findlib.Package.t) ~dir_contents ~ext_lib ~external_loc
143143
let implements = None in
144144
let parameters = [] in
145145
let orig_src_dir = None in
146+
let local_main_module_name = None in
146147
let main_module_name : Lib_info.Main_module_name.t = This None in
147148
let enabled = Memo.return Lib_info.Enabled_status.Normal in
148149
let requires =
@@ -252,6 +253,7 @@ let to_dune_library (t : Findlib.Package.t) ~dir_contents ~ext_lib ~external_loc
252253
~version
253254
~synopsis
254255
~main_module_name
256+
~local_main_module_name
255257
~sub_systems
256258
~requires
257259
~parameters

src/dune_rules/gen_rules.ml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,14 @@ let gen_rules_regular_directory (sctx : Super_context.t Memo.t) ~src_dir ~compon
533533
(* XXX sync this list with the pattern matches above. It's quite ugly
534534
we need this, we should rewrite this code to avoid this. *)
535535
Filename.Set.of_list
536-
[ ".js"; "_doc"; "_doc_new"; ".ppx"; ".dune"; ".topmod" ]
536+
[ ".js"
537+
; "_doc"
538+
; "_doc_new"
539+
; ".ppx"
540+
; ".dune"
541+
; ".topmod"
542+
; ".parameterized"
543+
]
537544
in
538545
Filename.Set.union automatic toplevel
539546
in
@@ -621,6 +628,10 @@ let gen_rules ctx sctx ~dir components : Gen_rules.result Memo.t =
621628
~dir
622629
(Subdir_set.of_set (Filename.Set.of_list [ "cc_vendor" ]))
623630
(fun () -> Configurator_rules.gen_rules ctx)
631+
| ".parameterized" :: rest ->
632+
let* sctx = sctx
633+
and* scope = Scope.DB.find_by_dir dir in
634+
Parameterized_rules.gen_rules ~sctx ~scope ~dir rest
624635
| _ -> gen_rules_regular_directory sctx ~src_dir ~components ~dir
625636
;;
626637

0 commit comments

Comments
 (0)