Skip to content

Commit 73b3232

Browse files
committed
feat: Add ppx-recorder that introduces the register_sampler calls
* New ppx called ppx-recorder that inserts `let () = Introspection.register_sampler name fun` for each toplevel binding prefixed with `sample_*` in test.ml. This ppx is applied during the precompilation of exercises. * Compilation units stored in `demo-repository/exercises/exercise_name/` during the precompilation are no longer staged.
1 parent a7977b5 commit 73b3232

8 files changed

+81
-3
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@ tests/corpuses/*
3535
detect-libs.*
3636

3737
docs/odoc.html
38+
39+
demo-repository/exercises/**/*.cmo
40+
demo-repository/exercises/**/*.cmi
41+
demo-repository/exercises/**/*.cma
42+
demo-repository/exercises/**/*.js

src/grader/grading_cli.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* included LICENSE file for details. *)
88

99
(** Take an exercise, a solution, and return the report, stdout,
10-
stderr and outcomes of the toplevel, or raise ont of the
10+
stderr and outcomes of the toplevel, or raise one of the
1111
exceptions defined in module {!Grading}. *)
1212
val get_grade:
1313
?callback:(string -> unit) ->

src/ppx-recorder/dune

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
(library
2+
(name ppx_recorder_lib)
3+
(wrapped false)
4+
(flags :standard -w -27)
5+
(modules Ppx_recorder)
6+
(preprocess (pps learnocaml_ppx_metaquot))
7+
(libraries ppxlib))
8+
9+
(library
10+
(name ppx_recorder)
11+
(wrapped false)
12+
(modules Ppx_recorder_register)
13+
(kind ppx_rewriter)
14+
(libraries ppx_recorder_lib))
15+
16+
(executable
17+
(name ppx_recorder_main)
18+
(modules Ppx_recorder_main)
19+
(libraries ppx_recorder))
20+
21+
(install
22+
(section libexec)
23+
(package learn-ocaml)
24+
(files
25+
(ppx_recorder_main.exe as grading_ppx/learnocaml-ppx-recorder))
26+
)

src/ppx-recorder/ppx_recorder.ml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
open Ppxlib
2+
3+
let rec get_samplers bindings acc =
4+
match bindings with
5+
| [] -> List.rev acc
6+
| binding :: rest -> (
7+
match binding.pvb_pat.ppat_desc with
8+
| Ppat_var var -> (
9+
match String.index_opt var.txt '_' with
10+
| Some i when String.sub var.txt 0 i = "sample" ->
11+
let suffix =
12+
String.sub var.txt (i + 1) (String.length var.txt - i - 1)
13+
in
14+
get_samplers rest (suffix :: acc)
15+
| _ -> get_samplers rest acc)
16+
| _ -> get_samplers rest acc)
17+
18+
let sampler_recorder s =
19+
let create_sampler_registration name sampler =
20+
[%stri let () = Introspection.register_sampler [%e name] [%e sampler]]
21+
in
22+
List.fold_right
23+
(fun si acc ->
24+
match si.pstr_desc with
25+
| Pstr_value (_, bindings) -> (
26+
match get_samplers bindings [] with
27+
| [] -> si :: acc
28+
| samplers ->
29+
let sampler_registration =
30+
List.map
31+
(fun sampler ->
32+
create_sampler_registration
33+
(Ast_builder.Default.estring ~loc:Location.none sampler)
34+
(Ast_builder.Default.evar ~loc:Location.none
35+
("sample_" ^ sampler)))
36+
samplers
37+
in
38+
(si :: sampler_registration) @ acc)
39+
| _ -> si :: acc)
40+
s []
41+
42+
let expand = sampler_recorder

src/ppx-recorder/ppx_recorder_main.ml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
let () =
2+
Ppxlib.Driver.run_as_ppx_rewriter ()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
let () =
2+
Ppxlib.Driver.register_transformation "sample_recorder" ~impl:Ppx_recorder.expand

src/repo/learnocaml_precompile_exercise.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ let precompile ~exercise_dir =
6161
jsoo ~dir [] ~source:"exercise.cma" ~target:"exercise.js");
6262
(ocamlc ~dir ["-c";
6363
"-I"; "+compiler-libs";
64-
"-ppx"; Filename.concat !grading_ppx_dir "learnocaml-ppx-metaquot" ]
64+
"-ppx"; Filename.concat !grading_ppx_dir "learnocaml-ppx-metaquot";
65+
"-ppx"; Filename.concat !grading_ppx_dir "learnocaml-ppx-recorder"]
6566
~opn:["Learnocaml_callback"; "Prelude"; "Prepare"; "Test_lib.Open_me"]
6667
~source:["test.ml"]
6768
~target:"test.cmo"

src/toploop/toploop_unix.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ val flush_redirected_channel : redirection -> unit
3333
(** Flushes the channel and then cancel the redirection.
3434
The redirection must be the last one performed, otherwise an
3535
[Invalid_argument] will be raised.
36-
A stack of redirections is maintained for all fire descriptors. So
36+
A stack of redirections is maintained for all file descriptors. So
3737
the channel is then restored to either the previous redirection or
3838
to the original file descriptor. *)
3939
val stop_channel_redirection : redirection -> unit

0 commit comments

Comments
 (0)