How to add a new frontend to `ortac` -- a tutorial
--------------------------------------------------
`ortac` is organised in a modular way that makes it easy to add a new
behaviour. The new behaviour is implemented by a frontend.
## The new files
In order to add a new frontend to `ortac` it is necessary to create
the following files in the `ortac` file tree:
```
|- src
|- newfrontend
|- dune
|- ortac_newfrontend.ml
|- ortac_newfrontend.mli
```
`ortac_newfrontend.mli` exposes one function: `generate: string -> unit`
that takes the path of the original module's signature as argument and
should print the generated code on `stdout`
`ortac_newfrontend.ml` contains at least three things.
First, a module `M` which signature is `Ortac_core.Backend.S` (**todo**: change name). This module define an expression `prelude` that is a `Ppxlib.structure` corresponding to the code that will be inserted before
the wrapper. Its main function is to open `Ortac_runtime` and to give
the opportunity to redefine some of its functions.
There are two functions in `Ortac_runtime` that are especially
interesting to redefine:
- `register : t -> error -> unit`
- `report : t -> unit`
The first allows specialisation of the set errors that will be
reported, and the latter allows specialisation of the way errors are
reported.
For example, if we don't want to report errors occurring during
a specification verification, we will redefine `register` this way:
```
let register t e =
match e with
| Specification_failure _ -> ()
| e -> t.errors <- e :: t.errors
```
The second thing that `ortac_newfrontend.ml` defines is always the same:
`module G = Ortac_core.Ortac.Make (M)`. That define the function `M.signature: string -> Gospel.Tast.signature -> Ppxlib.structure`. This function generate
the wrapper with the runtime defined in the module `M`.
The third thing that `ortac_newfrontend.ml` defines is the function `generate`. This function makes use of `M.signature` to generate the code,
but can also add some custom code if necessary.
## A new runtime
If the new frontend needs a runtime, it is possible to add it in the
file tree as follow:
```
|- ortac-runtime-newfrontend.opam
|- src
|- newfrontend
|- dune
|- ortac_newfrontend.ml
|- ortac_newfrontend.mli
|- runtime
|- dune
|- ortac_runtime_newfrontend.ml
|- ortac_runtime_newfrontend.mli
```
`ortac_runtime_newfrontend` is a package (it will be called by the generated code, which should not depends on `ortac`, so it is necessary to add the
`ortac-runtime-newfrontend.opam` file.
## Commande line parsing
In `bin/cli.ml`, we should add the newfrontend to the variant `frontend`
and completing the corresponding pattern matching in `frontend_printer`, `frontend_parser` and `main`.
In `main`, the branch `Newfrontend` should call `Ortac_newfrontend.generate`