Skip to content

Commit 7f3beb9

Browse files
authored
Revert "Allow execution of included OCaml code blocks" (#451)
1 parent 8c0bfb3 commit 7f3beb9

File tree

12 files changed

+77
-201
lines changed

12 files changed

+77
-201
lines changed

CHANGES.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
### unreleased
2+
3+
#### Changed
4+
5+
- Revert #446: "Allow execution of included OCaml code blocks" (#451, @gpetiot).
6+
Included OCaml code blocks preserve their pre-2.4.0 behavior.
7+
18
### 2.4.0
29

310
#### Added
411

512
- Handle the error-blocks syntax (#439, @jonludlam, @gpetiot)
613
- Allow execution of included OCaml code blocks. Add `skip` to `include` blocks
7-
to revert to the old behavior (#446, @panglesd)
14+
to revert to the old behavior (#446, @panglesd, @gpetiot)
15+
*Warning: this is a breaking change that is reverted in the next release.*
816
- Make MDX compatible with OCaml 5.2 (#448, @gpetiot)
917

1018
#### Fixed

lib/block.ml

Lines changed: 21 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,6 @@ let locate_errors ~loc r =
3030
(fun l -> List.map (fun (`Msg m) -> `Msg (locate_error_msg ~loc m)) l)
3131
r
3232

33-
module OCaml_kind = struct
34-
type t = Impl | Intf
35-
36-
let infer_from_file file =
37-
match Filename.(remove_extension (basename file), extension file) with
38-
| _, (".ml" | ".mlt" | ".eliom") -> Some Impl
39-
| _, (".mli" | ".eliomi") -> Some Intf
40-
| _ -> None
41-
end
42-
4333
module Header = struct
4434
type t = Shell of [ `Sh | `Bash ] | OCaml | Other of string
4535

@@ -95,13 +85,7 @@ type ocaml_value = {
9585
}
9686

9787
type toplevel_value = { env : Ocaml_env.t; non_det : Label.non_det option }
98-
99-
type include_ocaml_file = {
100-
part_included : string option;
101-
ocaml_value : ocaml_value option;
102-
kind : OCaml_kind.t;
103-
}
104-
88+
type include_ocaml_file = { part_included : string option }
10589
type include_other_file = { header : Header.t option }
10690

10791
type include_file_kind =
@@ -134,12 +118,6 @@ type t = {
134118
value : value;
135119
}
136120

137-
let get_ocaml_value t =
138-
match t.value with
139-
| OCaml ocaml_value -> Some ocaml_value
140-
| Include { file_kind = Fk_ocaml { ocaml_value; _ }; _ } -> ocaml_value
141-
| _ -> None
142-
143121
let dump_section = Fmt.(Dump.pair int string)
144122

145123
let header t =
@@ -212,22 +190,24 @@ let pp_error ?syntax ?delim ppf outputs =
212190
outputs err_delim
213191
| _ -> ()
214192

215-
let has_errors t =
216-
match get_ocaml_value t with
217-
| Some { errors = _ :: _; _ } -> true
193+
let has_output t =
194+
match t.value with
195+
| OCaml { errors = []; _ } -> false
196+
| OCaml { errors = _; _ } -> true
218197
| _ -> false
219198

220199
let pp_value ?syntax ppf t =
221200
let delim = t.delim in
222-
match get_ocaml_value t with
223-
| Some { errors; _ } ->
201+
match t.value with
202+
| OCaml { errors = []; _ } -> ()
203+
| OCaml { errors; _ } ->
224204
let errors = error_padding errors in
225205
pp_error ?syntax ?delim ppf errors
226206
| _ -> ()
227207

228208
let pp_footer ?syntax ppf t =
229209
let delim =
230-
if has_errors t then (
210+
if has_output t then (
231211
pp_value ?syntax ppf t;
232212
None)
233213
else t.delim
@@ -398,16 +378,13 @@ let get_block_config l =
398378
file_inc = get_label (function File x -> Some x | _ -> None) l;
399379
}
400380

401-
let mk_ocaml_value env non_det errors header =
402-
{ env = Ocaml_env.mk env; non_det; errors; header }
403-
404381
let mk_ocaml ~loc ~config ~header ~contents ~errors =
405382
let kind = "OCaml" in
406383
match config with
407384
| { file_inc = None; part = None; env; non_det; _ } -> (
408385
(* TODO: why does this call guess_ocaml_kind when infer_block already did? *)
409386
match guess_ocaml_kind contents with
410-
| `Code -> Ok (OCaml (mk_ocaml_value env non_det errors header))
387+
| `Code -> Ok (OCaml { env = Ocaml_env.mk env; non_det; errors; header })
411388
| `Toplevel ->
412389
loc_error ~loc "toplevel syntax is not allowed in OCaml blocks.")
413390
| { file_inc = Some _; _ } -> label_not_allowed ~loc ~label:"file" ~kind
@@ -445,38 +422,23 @@ let mk_toplevel ~loc ~config ~contents ~errors =
445422
let mk_include ~loc ~config ~header ~errors =
446423
let kind = "include" in
447424
match config with
448-
| { file_inc = Some file_included; part; non_det; env; _ } -> (
449-
let kind =
450-
match header with
451-
| Some Header.OCaml -> `OCaml
452-
| None -> (
453-
match OCaml_kind.infer_from_file file_included with
454-
| Some _ -> `OCaml
455-
| None -> `Other)
456-
| _ -> `Other
457-
in
458-
match kind with
459-
| `OCaml ->
460-
let kind =
461-
Util.Option.value ~default:OCaml_kind.Impl
462-
(OCaml_kind.infer_from_file file_included)
463-
in
464-
let part_included = part in
465-
let ocaml_value =
466-
match kind with
467-
| Impl -> Some (mk_ocaml_value env non_det errors header)
468-
| Intf -> None
469-
in
470-
let file_kind = Fk_ocaml { part_included; ocaml_value; kind } in
425+
| { file_inc = Some file_included; part; non_det = None; env = None; _ } -> (
426+
let* () = check_no_errors ~loc errors in
427+
match header with
428+
| Some Header.OCaml ->
429+
let file_kind = Fk_ocaml { part_included = part } in
471430
Ok (Include { file_included; file_kind })
472-
| `Other -> (
431+
| _ -> (
473432
match part with
474433
| None ->
475434
let file_kind = Fk_other { header } in
476435
Ok (Include { file_included; file_kind })
477436
| Some _ ->
478437
label_not_allowed ~loc ~label:"part" ~kind:"non-OCaml include"))
479438
| { file_inc = None; _ } -> label_required ~loc ~label:"file" ~kind
439+
| { non_det = Some _; _ } ->
440+
label_not_allowed ~loc ~label:"non-deterministic" ~kind
441+
| { env = Some _; _ } -> label_not_allowed ~loc ~label:"env" ~kind
480442

481443
let infer_block ~loc ~config ~header ~contents ~errors =
482444
match config with
@@ -561,18 +523,12 @@ let from_raw raw =
561523
~delim:None
562524

563525
let is_active ?section:s t =
564-
let active_section =
526+
let active =
565527
match s with
566528
| Some p -> (
567529
match t.section with
568530
| Some s -> Re.execp (Re.Perl.compile_pat p) (snd s)
569531
| None -> Re.execp (Re.Perl.compile_pat p) "")
570532
| None -> true
571533
in
572-
let can_update_content =
573-
match t.value with
574-
(* include blocks are always updated even if not executed *)
575-
| Include _ -> true
576-
| _ -> not t.skip
577-
in
578-
active_section && t.version_enabled && t.os_type_enabled && can_update_content
534+
active && t.version_enabled && t.os_type_enabled && not t.skip

lib/block.mli

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616

1717
(** Code blocks headers. *)
1818

19-
module OCaml_kind : sig
20-
type t = Impl | Intf
21-
end
22-
2319
module Header : sig
2420
type t = Shell of [ `Sh | `Bash ] | OCaml | Other of string
2521

@@ -51,8 +47,6 @@ type include_ocaml_file = {
5147
part_included : string option;
5248
(** [part_included] is the part of the file to synchronize with.
5349
If lines is not specified synchronize the whole file. *)
54-
ocaml_value : ocaml_value option;
55-
kind : OCaml_kind.t;
5650
}
5751

5852
type include_other_file = { header : Header.t option }

lib/test/mdx_test.ml

Lines changed: 29 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -190,19 +190,10 @@ let rec remove_padding ?(front = true) = function
190190
let xs = remove_padding ~front xs in
191191
x :: xs
192192

193-
let update_errors ~errors t =
194-
let update_ocaml_value (ov : Block.ocaml_value) = { ov with errors } in
195-
match t.Block.value with
196-
| OCaml v -> { t with value = OCaml (update_ocaml_value v) }
197-
| Include
198-
({ file_kind = Fk_ocaml ({ ocaml_value = Some v; _ } as fk); _ } as i) ->
199-
let ocaml_value = Some (update_ocaml_value v) in
200-
let file_kind = Block.Fk_ocaml { fk with ocaml_value } in
201-
{ t with value = Include { i with file_kind } }
202-
| _ -> assert false
203-
204-
let update_include ~contents = function
205-
| { Block.value = Include _; _ } as b -> { b with contents }
193+
let update_ocaml ~errors = function
194+
| { Block.value = OCaml v; _ } as b ->
195+
{ b with value = OCaml { v with errors } }
196+
(* [eval_ocaml] only called on OCaml blocks *)
206197
| _ -> assert false
207198

208199
let rec error_padding = function
@@ -215,7 +206,7 @@ let rec error_padding = function
215206
let contains_warnings l =
216207
String.is_prefix ~affix:"Warning" l || String.is_infix ~affix:"\nWarning" l
217208

218-
let eval_ocaml ~(block : Block.t) ?root c errors =
209+
let eval_ocaml ~(block : Block.t) ?syntax ?root c ppf errors =
219210
let cmd = block.contents |> remove_padding in
220211
let error_lines =
221212
match eval_test ?root ~block c cmd with
@@ -238,7 +229,8 @@ let eval_ocaml ~(block : Block.t) ?root c errors =
238229
| `Output x -> `Output (ansi_color_strip x))
239230
(Output.merge output errors)
240231
in
241-
update_errors ~errors block
232+
let updated_block = update_ocaml ~errors block in
233+
Block.pp ?syntax ppf updated_block
242234

243235
let lines = function Ok x | Error x -> x
244236

@@ -286,12 +278,9 @@ let read_part file part =
286278
(match part with None -> "" | Some p -> p)
287279
file
288280
| Some lines ->
289-
(* in any [string] element of lines, there might be newlines. *)
290281
let contents = String.concat ~sep:"\n" lines in
291282
String.drop contents ~rev:true ~sat:Char.Ascii.is_white
292283
|> String.drop ~sat:(function '\n' -> true | _ -> false)
293-
|> (fun contents -> "\n" ^ contents ^ "\n")
294-
|> String.cuts ~sep:"\n"
295284

296285
let write_parts ~force_output file parts =
297286
let output_file = file ^ ".corrected" in
@@ -303,13 +292,18 @@ let write_parts ~force_output file parts =
303292
flush oc;
304293
close_out oc
305294

306-
let update_file_or_block ?root md_file ml_file block part =
295+
let update_block_content ?syntax ppf t content =
296+
Block.pp_header ?syntax ppf t;
297+
Fmt.string ppf "\n";
298+
Output.pp ppf (`Output content);
299+
Fmt.string ppf "\n";
300+
Block.pp_footer ?syntax ppf t
301+
302+
let update_file_or_block ?syntax ?root ppf md_file ml_file block part =
307303
let root = root_dir ?root ~block () in
308304
let dir = Filename.dirname md_file in
309305
let ml_file = resolve_root ml_file dir root in
310-
let contents = read_part ml_file part in
311-
let new_block = update_include ~contents block in
312-
new_block
306+
update_block_content ?syntax ppf block (read_part ml_file part)
313307

314308
exception Test_block_failure of Block.t * string
315309

@@ -343,44 +337,26 @@ let run_exn ~non_deterministic ~silent_eval ~record_backtrace ~syntax ~silent
343337
in
344338
let preludes = preludes ~prelude ~prelude_str in
345339

346-
let run_ocaml_value t Block.{ env; non_det; errors; header = _; _ } =
347-
let det () =
348-
Mdx_top.in_env env (fun () -> eval_ocaml ~block:t ?root c errors)
349-
in
350-
with_non_det non_deterministic non_det
351-
~on_skip_execution:(fun () -> t)
352-
~on_keep_old_output:det ~on_evaluation:det
353-
in
354-
355340
let test_block ~ppf ~temp_file t =
356341
let print_block () = Block.pp ?syntax ppf t in
357342
if Block.is_active ?section t then
358343
match Block.value t with
359344
| Raw _ -> print_block ()
360-
| Include
361-
{
362-
file_included;
363-
file_kind = Fk_ocaml { part_included; ocaml_value; _ };
364-
} ->
345+
| Include { file_included; file_kind = Fk_ocaml { part_included } } ->
365346
assert (syntax <> Some Cram);
366-
let new_block =
367-
update_file_or_block ?root file file_included t part_included
368-
in
369-
let updated_block =
370-
match ocaml_value with
371-
(* including without executing *)
372-
| Some _ when t.skip -> new_block
373-
| Some ocaml_value -> run_ocaml_value new_block ocaml_value
374-
| _ -> new_block
375-
in
376-
Block.pp ?syntax ppf updated_block
347+
update_file_or_block ?syntax ?root ppf file file_included t
348+
part_included
377349
| Include { file_included; file_kind = Fk_other _ } ->
378-
let contents = read_part file_included None in
379-
let new_block = update_include ~contents t in
380-
Block.pp ?syntax ppf new_block
381-
| OCaml ov ->
382-
let updated_block = run_ocaml_value t ov in
383-
Block.pp ?syntax ppf updated_block
350+
let new_content = read_part file_included None in
351+
update_block_content ?syntax ppf t new_content
352+
| OCaml { non_det; env; errors; header = _ } ->
353+
let det () =
354+
assert (syntax <> Some Cram);
355+
Mdx_top.in_env env (fun () ->
356+
eval_ocaml ~block:t ?syntax ?root c ppf errors)
357+
in
358+
with_non_det non_deterministic non_det ~on_skip_execution:print_block
359+
~on_keep_old_output:det ~on_evaluation:det
384360
| Cram { language = _; non_det } ->
385361
let tests = Cram.of_lines t.contents in
386362
with_non_det non_deterministic non_det ~on_skip_execution:print_block

test/bin/mdx-test/expect/dune.inc

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,18 +179,6 @@
179179
(alias runtest)
180180
(action (diff errors/test-case.md errors.actual)))
181181

182-
(rule
183-
(target exec-include.actual)
184-
(deps (package mdx) (source_tree exec-include))
185-
(action
186-
(with-stdout-to %{target}
187-
(chdir exec-include
188-
(run ocaml-mdx test --output - test-case.md)))))
189-
190-
(rule
191-
(alias runtest)
192-
(action (diff exec-include/test-case.md exec-include.actual)))
193-
194182
(rule
195183
(target exit.actual)
196184
(deps (package mdx) (source_tree exit))

test/bin/mdx-test/expect/exec-include/code.ml

Lines changed: 0 additions & 7 deletions
This file was deleted.

test/bin/mdx-test/expect/exec-include/code.mli

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)