# Generating infix extension nodes with Ppxlib

**URL:** <https://discuss.ocaml.org/t/generating-infix-extension-nodes-with-ppxlib/14833>\
**Category:** Ecosystem\
**Tags:** ppxlib, ppx\
**Created:** [June 21, 2024, 9:01pm UTC](https://discuss.ocaml.org/t/generating-infix-extension-nodes-with-ppxlib/14833 "2024-06-21T21:01:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ngernest](https://avatars.discourse-cdn.com/v4/letter/n/3da27b/32.png) [@ngernest](https://discuss.ocaml.org/u/ngernest)\
**Post date:** [June 21, 2024, 9:01pm UTC](https://discuss.ocaml.org/t/generating-infix-extension-nodes-with-ppxlib/14833/1 "2024-06-21T21:01:10Z")

</div>

Hi! I’m working on a PPX deriver for property-based testing that produces testing code utilizing Jane Street’s `Core.Quickcheck` library. Specifically, I would like my PPX to produce monadic bind expressions that use the library’s `let%bind` syntax (the infix form of the extension node `[%bind ...]`), such as the following:

```ocaml
(* sample an int from a monadic Quickcheck generator [gen_int], 
  using [ppx_jane] *)
let%bind x = gen_int in ...

```

Right now, my PPX deriver produces the expression above by calling the function `pexp_extension` (in [`Ppxlib.Ast_builder.Default`](https://ocaml-ppx.github.io/ppxlib/ppxlib/Ppxlib/Ast_builder/Default/index.html)) and using [Metaquot quotations](https://ocaml-ppx.github.io/ppxlib/ppxlib/generating-code.html) to produce a `Pexp_extension` AST node:

```ocaml
pexp_extension ({txt = "bind", ...},
      PStr [pstr_eval ~loc [%expr let x = gen_int in ...] ...]) ...

```

This produces the following:

```ocaml
[%bind let x = gen_int in ...]

```

I understand from the [OCaml language manual](https://ocaml.org/manual/5.2/extensionnodes.html) that the `let%bind ...` infix form desugars to `[%bind ...]`.

I was wondering if it would be possible for my PPX deriver to directly produce the `let%bind` syntactic form via Ppxlib? I understand if this is infeasible since this desugaring is typically done by another PPX (`ppx_jane`).

Thanks!

---

<div class="post-metadata">

**Author:** ![v-gb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/v-gb/32/5080_2.png) [@v-gb](https://discuss.ocaml.org/u/v-gb)\
**Post date:** [June 22, 2024, 11:31am UTC](https://discuss.ocaml.org/t/generating-infix-extension-nodes-with-ppxlib/14833/2 "2024-06-22T11:31:59Z")

</div>

> [@ngernest](#):
>
> I was wondering if it would be possible for my PPX deriver to directly produce the `let%bind` syntactic form via Ppxlib?

`let%bind p = e1 in e2` and `[%bind let p = e1 in e2]` are represented as the same AST, which you are generating correctly, so there’s nothing different you can do. It’s the same as how `1 + 2` and `(+) 1 2` have the same AST.

Maybe your question is “when I pretty-print that AST, how I can get `let%bind ..` instead of `[%bind let ...]` ?”. For that, usually you can’t choose a specific concrete syntax, but it probably depends on the pretty printer. I don’t know what the compiler printer does. I think ocamlformat looks at AST positions to distinguish ASTs from `let%bind ...` vs ASTs from `[%bind ...]`, and display the same syntax as the source code.

As a side remark, if you’re using metaquot, you should be able to use it some more to simplify your code further. All these should generate the same AST:

```ocaml
pexp_extension ~loc ({txt = "bind"; loc},
                     PStr [pstr_eval ~loc [%expr let x = gen_int in ()] []])
pexp_extension ~loc ({txt = "bind"; loc},
                     PStr [[%stri let x = gen_int in ()]])
pexp_extension ~loc ({txt = "bind"; loc},
                     PStr [%str let x = gen_int in ()])
[%expr let%bind x = gen_int in ()]

```

(and you could also use `Ppx_let_expander.expand` to directly expand the `%bind` code instead of requiring users of your ppx to also list `ppx_let` in their dune file, with the downside that the `Ppx_let_expander` API presumably gets breaking changes from times to times).

---

<div class="post-metadata">

**Author:** ![ngernest](https://avatars.discourse-cdn.com/v4/letter/n/3da27b/32.png) [@ngernest](https://discuss.ocaml.org/u/ngernest)\
**Post date:** [June 22, 2024, 4:16pm UTC](https://discuss.ocaml.org/t/generating-infix-extension-nodes-with-ppxlib/14833/3 "2024-06-22T16:16:23Z")

</div>

Thanks for the reply, especially the tips on using Metaquot to make the PPX code more succinct!  
I’ll look into using the `Ppx_let_expander` API, and if that doesn’t work I’ll just make my PPX generate monadic code that uses the infix `>>=` operator (instead of `let%bind ...`).
