Hello, is it possible to use a ppx with mdx?
Given these 2 files:
Dune file
(mdx
(libraries async async_kernel ppx_let))
Markdown file
MDX ok
```ocaml
let add a b = a + b
```
---
MDX ok
```ocaml
# add 1 2
- : int = 3
```
---
MDX not ok: `Error: Uninterpreted extension 'map'`
```ocaml
open Async;;
open Deferred.Result.Let_syntax;;
let promise =
let%map number = Deferred.return (Ok 1) in number;;
```
When I run dune runtest
, I get a compilation error.
Unfortunately, Duneβs preprocess
stanza is not compatible inside the mdx stanza so Iβm not sure if what I want is possible at the moment.
1 Like
Iβm not exactly sure how to do it for PPX extensions based on the standard infrastructure, but I was able to do it for those based on camlp5 and it was very simple: just act as if MDX is a standard top level β I donβt mean a dune top level but rather a normal top level β and dump in the commands that you would need to enable PPX rewriting In that top level.
So I suppose this might not help in the sense that now you have to figure out how to do PPX rewriting in a normal top level. But I seem to remember somebody wrote that up somewhere.
I doubt this will be useful to you because this is based on camlp5, but hereβs an MDX compatible doc file that I wrote a while back: https://github.com/camlp5/pa_ppx_regexp/blob/master/README.asciidoc
P.S. Specifically, I call your attention to this section: https://github.com/camlp5/pa_ppx_regexp/blob/master/README.asciidoc#from-the-ocaml-toplevel
Thanks. Your nudging made me think about it a little more.
I did find that I had to require βppx_letβ if I wanted to test the async lib without a dune project, like so:
β( 14:42:01 )β< command 0 >ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{ counter: 0 }β
utop # #require "async";;
β( 14:42:01 )β< command 1 >ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{ counter: 0 }β
utop # open Async;;
β( 14:42:08 )β< command 2 >ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{ counter: 0 }β
utop # open Deferred.Result.Let_syntax;;
β( 14:42:13 )β< command 3 >ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{ counter: 0 }β
utop # let promise = let%map number = Deferred.return (Ok 1) in number;;
Error: Uninterpreted extension 'map'.
β( 14:42:18 )β< command 4 >ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{ counter: 0 }β
utop # #require "ppx_let";;
β( 14:42:23 )β< command 5 >ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{ counter: 0 }β
utop # let promise = let%map number = Deferred.return (Ok 1) in number;;
val promise : (int, 'a) Async_kernel__Deferred_result.t = <abstr>
This also works with the standard ocaml
REPL.
This made me realize I had to βrequireβ it too, as if mimicking a REPL, then run βnormalβ OCaml via MDX. Even though I listed ppx_let
as a dependency in my MDX project. My guess is that some code doesnβt auto-load under an MDX context.
Hereβs a complete example that works :
==> dune <==
(mdx
(libraries async async_kernel async_unix core ppx_let))
==> dune-project <==
(lang dune 3.10)
(using mdx 0.4)
==> REAME.md <==
MDX ok
```ocaml
let add a b = a + b
```
---
MDX ok
```ocaml
# add 1 2
- : int = 3
```
---
MDX ok
```ocaml
# #require "ppx_let";;
# open Async;;
# open Core;;
# open Deferred.Result.Let_syntax;;
# let promise_one =
let%map one = Deferred.return (Core.Ok 1) in one;;
val promise_one : (int, 'a) Async_kernel__Deferred_result.t = <abstr>
```
---
MDX ok!
```ocaml
open Async;;
open Core;;
open Deferred.Result.Let_syntax;;
let promise_two =
let%map two = Deferred.return (Core.Ok 2) in two;;
```
---
MDX final check ok!
```ocaml
# let ok_one = Async.Thread_safe.block_on_async_exn @@ fun () -> promise_one;;
val ok_one : (int, 'a) Core._result = Core.Result.Ok 1
# let ok_two = Async.Thread_safe.block_on_async_exn @@ fun () -> promise_two;;
val ok_two : (int, 'a) Core._result = Core.Result.Ok 2
# add (Core.ok_exn ok_one) (Core.ok_exn ok_two);;
- : int = 3
```
1 Like
I figured out a way to use ppx for mdx, indirectly.
- You can make a normal
sync_to_md.ml
file with normal dune
but with MDX wrapping comments.
(* $MDX part-begin=partName *)
type t = int [@@deriving_inline hash] [@@@end]
(* $MDX part-end *)
Just dune build
your file as a normal ocaml project.
- Include that part in your md file with the reference tags.
<!-- $MDX file=path/to/sync_to_md.ml,part=partName -->
```ocaml
``'
Run normal mdx command dune runtest
then dune promote
.