aycc
aycc

Reputation: 167

OCaml: Automate custom pretty-printer installing

I have implemented a pretty-printer for a module. Currently I start up utop, load the dependencies then do #install_printer pp_custom;; where pp_custom is the pretty-printer.

I would like to automate this so that I can have it in a way that is similar to the lacaml library where the pretty-printer for the matrix is "installed" by default.

How would I go about to doing that?

Upvotes: 1

Views: 986

Answers (1)

ivg
ivg

Reputation: 35210

In short, you need to run #install_printer directive whenever you load your library in the top. I'm using the following code to evaluate code in the toplevel:

open Core_kernel.Std
open Or_error

let eval_exn str =
  let lexbuf = Lexing.from_string str in
  let phrase = !Toploop.parse_toplevel_phrase lexbuf in
  Toploop.execute_phrase false Format.err_formatter phrase

let eval str = try_with (fun () -> eval_exn str)

It depends on Core_kernel, but you can get rid of this easily, by just using eval_exn instead of eval (the last one wraps a possible exception into the Or_error monad). Once you've got the eval function, it can be used to load your printers:

 let () = eval (sprintf "#install_printer %s;;" printer)

where printer is the name of the pretty printing function (usually qualified with a module name). Usually, one put such code into the separate library, named library.top, where library is the name of your library.

For further automation, you can require all types, that you want to be auto-printable in toplevel, to register itself in a central registry, and then call all registered printers, instead of enumerating them by hand. To see all this working at once, you can take a look at the BAP library. It has a sublibrary called bap.top that automatically installs all printers. Each type that is desired to be printable implements Printable signature, using Printable.Make functor, that not only derives many printing functions from the basic definition, but also registers the generated pretty-printers in Core_kernel's Pretty_printer registry (you can use your own registry, this is just a set of strings, nothing more). When bap.top library is loaded into the toplevel (using require or load directive), it enumerates all registered printers and install them.

Upvotes: 5

Related Questions