# Generation of OCaml code

**URL:** <https://discuss.ocaml.org/t/generation-of-ocaml-code/2159>\
**Category:** Learning\
**Tags:** code-generation, metaprogramming, jbuilder, build, dune\
**Created:** [June 16, 2018, 7:08pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159 "2018-06-16T19:08:15Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![egoholic](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/egoholic/32/574_2.png) [@egoholic](https://discuss.ocaml.org/u/egoholic)\
**Post date:** [June 16, 2018, 7:08pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/1 "2018-06-16T19:08:15Z")

</div>

I’m working on router in which I would describe routes using S-expressions (sexplib), for example see the screenshot below. What is the best way to translate S-expressions in OCaml while building (I use Dune/Jbuilder)?

 ![46%20PM](https://us1.discourse-cdn.com/flex020/uploads/ocaml/original/2X/9/99f6769f3267b136d3c47ce08ed45a04af9e907b.png)

**_IMPORTANT!_** : My question is not about how to do this with Dune/Jbuilder, but about generation of OCaml code itself.

---

<div class="post-metadata">

**Author:** ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)\
**Post date:** [June 16, 2018, 7:43pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/2 "2018-06-16T19:43:08Z")

</div>

Beyond the basic printf based generator, a simple solution might be to use the `compiler-libs` library to create a small custom compiler (or you could just generate OCaml ast) and then add the corresponding rules and dependency to dune.

---

<div class="post-metadata">

**Author:** ![egoholic](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/egoholic/32/574_2.png) [@egoholic](https://discuss.ocaml.org/u/egoholic)\
**Post date:** [June 16, 2018, 9:34pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/3 "2018-06-16T21:34:53Z")

</div>

`compiler-libs` looks interesting to me, but I suggest it would be harder to use it than the variant with string concatenation or something like that.

---

<div class="post-metadata">

**Author:** ![mseri](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mseri/32/91_2.png) [@mseri](https://discuss.ocaml.org/u/mseri)\
**Post date:** [June 16, 2018, 9:55pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/4 "2018-06-16T21:55:30Z")

</div>

Why not simply write a code generator that parse the sexp and saves it to a file as an ocaml software? Then in dune you can define a rule target for the output file that calls this executable (that itself could be defined as a target executable). See for example: [https://github.com/xapi-project/xen-api/blob/master/ocaml/xapi/jbuild](https://github.com/xapi-project/xen-api/blob/master/ocaml/xapi/jbuild)

---

<div class="post-metadata">

**Author:** ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)\
**Post date:** [June 16, 2018, 10:25pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/5 "2018-06-16T22:25:23Z")

</div>

> [@egoholic](#):
>
> `compiler-libs` looks interesting to me, but I suggest it would be harder to use it than the variant with string concatenation or something like that.

Indeed, generating ast (with compiler-libs + ppx\_metaquot) has a higher entry cost that simply concatenating strings, but it can be more reliable and maintainable in the long term.

---

<div class="post-metadata">

**Author:** ![egoholic](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/egoholic/32/574_2.png) [@egoholic](https://discuss.ocaml.org/u/egoholic)\
**Post date:** [June 17, 2018, 7:56am UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/6 "2018-06-17T07:56:15Z")

</div>

This is exactly what I want to do (see IMPORTANT section in the bottom of my question). My question was about code generation itself. I thought about simple string concatenation and was asking about alternatives to that approach.

@octachron has recommended to take a look at `compiler-lib` which looks very intriguing to me but, as for an OCaml newbie, it looks like substantially more work. I think I will use stupid simple string concatenation for the first version but I’ll keep in mind `compiler-lib` for refactoring in future.

---

<div class="post-metadata">

**Author:** ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)\
**Post date:** [June 18, 2018, 5:42pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/7 "2018-06-18T17:42:33Z")

</div>

If generating OCaml code without location directives pointing to the source is acceptable to you, you can use the [approach that we use in atdgen](https://github.com/mjambon/atd/blob/master/atdgen/src/indent.mli). Instead of writing just printfs and trying to keep track of the indentation, we produce a _tree of lines of code_.

You can define your own, it’s straightforward:

```auto
type t =
| Line of string (**single line (not indented)**)
| Block of t list ( **indented sequence** )
| Inline of t list (**in-line sequence (not indented)**)

```

The functions that generate OCaml code return a `t list` rather than writing to a buffer. Here’s a random sample:

```auto
let l =
  insert (Line "Bi_outbuf.add_char ob ',';") (Array.to_list a)
in
let op, cl =
  if p.std then '[', ']'
  else '(', ')'
in
[
  Block [
    Line (sprintf "Bi_outbuf.add_char ob %C;" op);
    Inline l;
    Line (sprintf "Bi_outbuf.add_char ob %C;" cl);
  ]
]

```

---

<div class="post-metadata">

**Author:** ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)\
**Post date:** [June 18, 2018, 5:54pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/8 "2018-06-18T17:54:01Z")

</div>

> [@mjambon](#):
>
> Instead of writing just printfs and trying to keep track of the indentation, we produce a _tree of lines of code_ .

It seems quite similar to `Format`’s formatting boxes: blocks sound like `@[<hv 2>...@]` (or `@[<v 2>...@]` ?), and Inline might be `<hov>` (or `<h>`?).

---

<div class="post-metadata">

**Author:** ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)\
**Post date:** [June 18, 2018, 8:29pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/9 "2018-06-18T20:29:01Z")

</div>

> [@octachron](#):
>
> It seems quite similar to `Format` 's formatting boxes

Yes, except that the solution I’m proposing here produces subpar code (long lines, wasted whitespace). The goal here is to increase the readability of the generator’s source code, at the expense of reducing the readability of the generated code. It’s a worthy trade-off when the generated code is boilerplate that rarely has tricky bugs. Also, `Format` can be slow on some pathological input. I don’t know if it’s typical on generated code, but it’s nice to know it won’t happen.

For higher-quality output, we have [easy-format](https://github.com/mjambon/easy-format), which is a functional wrapper around the `Format` module. Even though I’m the original author, I find it too cumbersome and not worth the effort if the user isn’t going to read the generated code.

---

<div class="post-metadata">

**Author:** ![Arto](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/arto/32/2344_2.png) [@Arto](https://discuss.ocaml.org/u/Arto)\
**Post date:** [June 23, 2018, 7:44am UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/10 "2018-06-23T07:44:45Z")

</div>

There is also [https://github.com/stedolan/malfunction](https://github.com/stedolan/malfunction) that may be of interest.

---

<div class="post-metadata">

**Author:** ![rixed](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rixed/32/56_2.png) [@rixed](https://discuss.ocaml.org/u/rixed)\
**Post date:** [June 28, 2018, 7:10am UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/11 "2018-06-28T07:10:31Z")

</div>

I wouldn’t worry about indentation so much. Why not use a tool such as ocp-indent, either when you want to read the file or as the last stage of your generation process (so that location directives are correct)?

---

<div class="post-metadata">

**Author:** ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)\
**Post date:** [June 28, 2018, 5:21pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/12 "2018-06-28T17:21:26Z")

</div>

I’m sure ocp-indent is suitable in some cases but AFAIK it won’t break or merge lines for you. e.g.

```auto
let x =
  f a
  || f b

```

won’t be turned into

```auto
let x = f a || f b

```

---

<div class="post-metadata">

**Author:** ![hcarty](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hcarty/32/1824_2.png) [@hcarty](https://discuss.ocaml.org/u/hcarty)\
**Post date:** [June 28, 2018, 6:37pm UTC](https://discuss.ocaml.org/t/generation-of-ocaml-code/2159/13 "2018-06-28T18:37:11Z")

</div>

You could use [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) for that.
