@@ -97,15 +97,11 @@ module Run (P : PARAMS) = struct
9797 corresponding source file, and [targets m] is the list of targets that
9898 Menhir must build. *)
9999
100- let source m = Path. relative (Path. build dir) (m ^ " .mly" )
101-
102100 let targets m ~cmly =
103101 let base = [ m ^ " .ml" ; m ^ " .mli" ] in
104102 List. map ~f: (Path.Build. relative dir) (if cmly then (m ^ " .cmly" ) :: base else base)
105103 ;;
106104
107- let sources ms = List. map ~f: source ms
108-
109105 (* The following definitions control where the mock [.ml] file and the
110106 inferred [.mli] file are created and how they are named. *)
111107
@@ -187,49 +183,64 @@ module Run (P : PARAMS) = struct
187183 (* The current concrete name for [base] clauses is [merge_into], but I would
188184 like to change it in the future. *)
189185
190- let stanzas : stanza list =
191- match stanza.merge_into with
192- | None ->
193- List. map
194- ~f: (fun m -> { stanza with modules = [ m ]; merge_into = Some m })
195- stanza.modules
196- | Some _ -> [ stanza ]
186+ let stanzas : (stanza * Path.Set.t) list Memo.Lazy.t =
187+ Memo. lazy_ (fun () ->
188+ let open Memo.O in
189+ let + { Ml_sources.Parser_generators. deps; targets = _ } =
190+ let sctx = Compilation_context. super_context cctx in
191+ Dir_contents. get sctx ~dir
192+ >> = Dir_contents. ocaml
193+ >> | Ml_sources.Parser_generators. modules ~for_: (Menhir stanza.loc)
194+ in
195+ match stanza.merge_into with
196+ | None ->
197+ Path.Set. fold deps ~init: [] ~f: (fun p acc ->
198+ let merge_into = Filename. remove_extension (Path. basename p) in
199+ ({ stanza with merge_into = Some merge_into }, Path.Set. singleton p) :: acc)
200+ | Some _ -> [ stanza, deps ])
197201 ;;
198202
199203 (* ------------------------------------------------------------------------ *)
200204
201205 (* The [--infer-*] commands should not be passed by the user; we take care of
202206 using these commands appropriately. Fail if they are present. *)
203207
204- let () =
205- List. iter stanzas ~f: (fun (stanza : stanza ) ->
206- Ordered_set_lang.Unexpanded. fold_strings stanza.flags ~init: () ~f: (fun _pos sw () ->
207- match String_with_vars. text_only sw with
208- | None -> ()
209- | Some "--explain" ->
210- if stanza.menhir_syntax > = Dune_lang.Menhir. explain_since
211- then
212- User_error. raise
213- ~loc: (String_with_vars. loc sw)
214- [ Pp. textf
215- " The Menhir '.conflicts' file is generated by default, so '--explain' \
216- should not be explicitly added to the list of Menhir flags."
217- ]
218- | Some text ->
219- if
220- List. mem
221- ~equal: String. equal
222- [ " --depend"
223- ; " --raw-depend"
224- ; " --infer"
225- ; " --infer-write-query"
226- ; " --infer-read-reply"
227- ]
228- text
229- then
230- User_error. raise
231- ~loc: (String_with_vars. loc sw)
232- [ Pp. textf " The flag %s must not be used in a menhir stanza." text ]))
208+ let check =
209+ Memo. lazy_ (fun () ->
210+ let open Memo.O in
211+ Memo.Lazy. force stanzas
212+ >> | List. iter ~f: (fun ((stanza , _ ) : stanza * Path.Set. t ) ->
213+ Ordered_set_lang.Unexpanded. fold_strings
214+ stanza.flags
215+ ~init: ()
216+ ~f: (fun _pos sw () ->
217+ match String_with_vars. text_only sw with
218+ | None -> ()
219+ | Some "--explain" ->
220+ if stanza.menhir_syntax > = Dune_lang.Menhir. explain_since
221+ then
222+ User_error. raise
223+ ~loc: (String_with_vars. loc sw)
224+ [ Pp. textf
225+ " The Menhir '.conflicts' file is generated by default, so \
226+ '--explain' should not be explicitly added to the list of Menhir \
227+ flags."
228+ ]
229+ | Some text ->
230+ if
231+ List. mem
232+ ~equal: String. equal
233+ [ " --depend"
234+ ; " --raw-depend"
235+ ; " --infer"
236+ ; " --infer-write-query"
237+ ; " --infer-read-reply"
238+ ]
239+ text
240+ then
241+ User_error. raise
242+ ~loc: (String_with_vars. loc sw)
243+ [ Pp. textf " The flag %s must not be used in a menhir stanza." text ])))
233244 ;;
234245
235246 (* ------------------------------------------------------------------------ *)
@@ -238,14 +249,15 @@ module Run (P : PARAMS) = struct
238249 is the three-step process where Menhir is invoked twice and OCaml type
239250 inference is performed in between. *)
240251
241- let process3 base ~cmly (stanza : stanza ) : unit Memo.t =
252+ let process3 base ~cmly (( stanza , deps ) : stanza * Path.Set. t ) : unit Memo.t =
242253 let open Memo.O in
243254 let * expanded_flags = expand_flags stanza.flags in
244255 (* 1. A first invocation of Menhir creates a mock [.ml] file. *)
256+ let source_deps = Path.Set. to_list deps in
245257 let * () =
246258 menhir
247259 [ Command.Args. dyn expanded_flags
248- ; Deps (sources stanza.modules)
260+ ; Deps source_deps
249261 ; A " --base"
250262 ; Path (Path. relative (Path. build dir) base)
251263 ; A " --infer-write-query"
@@ -296,7 +308,7 @@ module Run (P : PARAMS) = struct
296308 menhir
297309 [ Command.Args. dyn expanded_flags
298310 ; S explain_flags
299- ; Deps (sources stanza.modules)
311+ ; Deps source_deps
300312 ; A " --base"
301313 ; Path (Path. relative (Path. build dir) base)
302314 ; A " --infer-read-reply"
@@ -311,7 +323,7 @@ module Run (P : PARAMS) = struct
311323 (* [process3 stanza] converts a Menhir stanza into a set of build rules. This
312324 is a simpler one-step process where Menhir is invoked directly. *)
313325
314- let process1 base ~cmly (stanza : stanza ) : unit Memo.t =
326+ let process1 base ~cmly (( stanza , deps ) : stanza * Path.Set. t ) : unit Memo.t =
315327 let open Memo.O in
316328 let * expanded_flags = expand_flags stanza.flags
317329 and * explain_flags = explain_flags base stanza
@@ -323,7 +335,7 @@ module Run (P : PARAMS) = struct
323335 menhir
324336 [ Command.Args. dyn expanded_flags
325337 ; S explain_flags
326- ; Deps (sources stanza.modules )
338+ ; Deps (Path.Set. to_list deps )
327339 ; A " --base"
328340 ; Path (Path. relative (Path. build dir) base)
329341 ; Hidden_targets (targets base ~cmly )
@@ -339,7 +351,7 @@ module Run (P : PARAMS) = struct
339351 (* Because Menhir processes [--only-tokens] before the [--infer-*] commands,
340352 when [--only-tokens] is present, no [--infer-*] command should be used. *)
341353
342- let process (stanza : stanza ) : unit Memo.t =
354+ let process (( stanza , sources ) : stanza * Path.Set. t ) : unit Memo.t =
343355 let base = Option. value_exn stanza.merge_into in
344356 let ocaml_type_inference_disabled, cmly =
345357 Ordered_set_lang.Unexpanded. fold_strings
@@ -355,24 +367,23 @@ module Run (P : PARAMS) = struct
355367 | Some _ | None -> acc))
356368 in
357369 if ocaml_type_inference_disabled || not stanza.infer
358- then process1 base stanza ~cmly
359- else process3 base stanza ~cmly
370+ then process1 base ( stanza, sources) ~cmly
371+ else process3 base ( stanza, sources) ~cmly
360372 ;;
361373
362374 (* ------------------------------------------------------------------------ *)
363- let gen_rules () = Memo. sequential_iter ~f: process stanzas
375+ let gen_rules () =
376+ let open Memo.O in
377+ let * () = Memo.Lazy. force check
378+ and * stanzas = Memo.Lazy. force stanzas in
379+ Memo. sequential_iter stanzas ~f: process
380+ ;;
364381end
365382
366383(* -------------------------------------------------------------------------- *)
367384
368385(* The final glue. *)
369386
370- let module_names (stanza : Menhir_stanza.t ) : Module_name.t list =
371- List. map (Menhir_stanza. modules stanza) ~f: (fun s ->
372- (* TODO the loc can improved here *)
373- Module_name. of_string_allow_invalid (stanza.loc, s))
374- ;;
375-
376387let gen_rules ~dir ~module_path cctx stanza =
377388 let module R =
378389 Run (struct
0 commit comments