Version française
Home     About     Download     Resources     Contact us    
Browse thread
Installing pretty-printers automagically
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Markus Mottl <markus.mottl@g...>
Subject: Installing pretty-printers automagically
Hi,

though the idea is not new, more precisely, I have shamelessly stolen
it from Gerd Stolpmann's findlib sources, it still seems not widespread
and is such a useful thing to have that it should be mentioned here on
the list.

You will quite often want to have custom pretty-printers for your
datatypes in the toplevel.  Preferably, they should be installed as
soon as the library implementing them has been loaded.

The solution for this is quite simple, and I have just implemented it
in the LACAML-library so that matrices and vectors can be printed in
the toplevel.

Assuming you have already implemented a pretty-printer with the correct
signature in module "My_module":

  val pp_my_type : Format.formatter -> my_type -> unit

Then just create another module in your library:                                
---------------------------------------------------------------------------
let printers =
  [
    "My_module.pp_my_type";
  ]

let eval_string
      ?(print_outcome = false) ?(err_formatter = Format.err_formatter) str =
  let lexbuf = Lexing.from_string str in
  let phrase = !Toploop.parse_toplevel_phrase lexbuf in
  Toploop.execute_phrase print_outcome err_formatter phrase

let rec install_printers = function
  | [] -> true
  | printer :: printers ->
      let cmd = Printf.sprintf "#install_printer %s;;" printer in
      eval_string cmd && install_printers printers

let () =
  if not (install_printers printers) then
    Format.eprintf "Problem installing printers@."
---------------------------------------------------------------------------

Just add further pretty-printers to the list "printers" if required.

If you link this module into a byte-code library and load it into the
toplevel (using #load), you will be able to print your types using the 
custom pretty-printers.

There is one caveat here: the resulting library cannot be used for linking
with byte-code executables, because the toplevel is not available there.  
Therefore, if you want to implement a library, you will have to link
two separate ones: one with and one without the module for installing
the printers.

If you happen to use "ocamlfind" to "#require" your libraries, you just
need to add a line to the META-file for each kind of library.  The right
one will be chosen automatically then, e.g.:

  archive(byte)="mylib.cma"
  archive(byte,toploop)="mylib_top.cma"

Here is a short demonstration using the pretty-printers of the
LACAML-library in the toplevel while computing the singular value
decomposition of a 3x3 Hilbert-matrix:

---------------------------------------------------------------------------
# #require "lacaml";;
/usr/local/home/godi/godi/lib/ocaml/std-lib/bigarray.cma: loaded
/usr/local/home/godi/godi/lib/ocaml/site-lib/lacaml: added to search path
/usr/local/home/godi/godi/lib/ocaml/site-lib/lacaml/lacaml_top.cma: loaded
# open Lacaml.D;;
# let mat = Mat.hilbert 3;;
val mat : Lacaml_float64.mat = 
         1      0.5 0.333333
       0.5 0.333333     0.25
  0.333333     0.25      0.2
# gesvd mat;;
- : Lacaml_float64.vec * Lacaml_float64.mat * Lacaml_float64.mat = 
(   1.40832
   0.122327
 0.00268734,
 -0.827045  0.547448  0.127659
 -0.459864  -0.52829 -0.713747
 -0.323298 -0.649007  0.688672,
 -0.827045 -0.459864 -0.323298
  0.547448  -0.52829 -0.649007
  0.127659 -0.713747  0.688672)
---------------------------------------------------------------------------

Enjoy this trick...

Best regards,
Markus

-- 
Markus Mottl        http://www.ocaml.info        markus.mottl@gmail.com