caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Alain Frisch <alain@frisch.fr>
To: Jeremie Dimino <jdimino@janestreet.com>,
	 Gabriel Kerneis <gabriel@kerneis.info>
Cc: "caml-list@inria.fr" <caml-list@inria.fr>
Subject: Re: [Caml-list] Extending Format strings
Date: Tue, 01 Jul 2014 18:06:44 +0200	[thread overview]
Message-ID: <53B2DC94.6050809@frisch.fr> (raw)
In-Reply-To: <CANhEzE4_gCgRRVNE+VCLhYwhvy-dpR3xwb8Yi4CyirZ1oWxR1g@mail.gmail.com>

On 07/01/2014 05:27 PM, Jeremie Dimino wrote:
> On Tue, Jul 1, 2014 at 10:59 AM, Gabriel Kerneis <gabriel@kerneis.info
> <mailto:gabriel@kerneis.info>> wrote:
>
>     Dear all,
>
>     in CIL <http://cil.sf.net>, the module Pretty provides a Format-like
>     interface with a few extensions compared to usual format strings.
>     Implementation-wise, it uses string_of_format and re-implements most of
>     the logic of the pre-4.02 Format module, with Obj.magic all over the
>     place.
>
>     I wondered if anyone has done something similar in their own project
>     (extending Format in one way or another), and if the new GADT-based
>     approach could provide a cleaner solution?
>
>     One thing I quite like with the current code, despite its uglyness, is
>     its concision. I am right in assuming that switching to GADTs would
>     require a lot more boilerplate?
>
>
> I had a quick look at [Pretty.dprintf] and I think you could use
> [CamlinternalFormat.make_printf] to implement it with 4.02. @-sequences
> are already recognized by the format parser in the compiler, but it
> should be compatible with [Pretty]'s syntax, you just have to interpret
> the constructors differently. It should actually make the code of
> [Pretty.dprintf] much simpler.

We had a very similar issue with some internal LexiFi library, also 
using @-markers, and returning some structured document.  Jeremie's 
suggestion works very well.

The code below won't compile, but it can give you an idea on how to proceed:


let printf_k fmt_s (acc : (unit, t) CamlinternalFormat.acc) =
   let open CamlinternalFormat in
   let l = ref empty in
   let add x = l := conc !l x in
   let stack = ref [] in
   let push x = stack := (x,!l) :: !stack; l := empty in
   let err () =
     Mlfi_isdatypes.ffailwith "Mlfi_pp.printf: invalid format string %S" 
fmt_s
   in
   let pop () = match !stack with
     | (x,old) :: st -> stack := st; let nl = !l in l := old; (x,nl)
     | _ -> err ()
   in
   let rec k = function
     | Acc_string(p, s) -> k p; add (str s)
     | Acc_char(p, c) -> k p; add (str (String.make 1 c))
     | Acc_delay(p, f) -> k p; add f
     | Acc_flush p -> k p
     | Acc_invalid_arg (_, msg) -> invalid_arg msg
     | Acc_formatting_lit (p, lit) ->
         k p;
         begin match string_of_formatting_lit lit with
         | "@[" -> push (`BoxLeft 2)
         | "@]" ->
             begin match pop () with
             | (`BoxLeft k,u) -> add (indent k u)
             | _ -> err ()
             end
         | "@<" -> push `LineLeft
         | "@>" ->
             begin match pop () with
             | `LineLeft, u -> add (line u)
             | _ -> err ()
             end
         | s ->
             add (str s)
         end
     | Acc_formatting_gen (p, _) -> k p
     | End_of_acc -> ()
   in
   k acc;
   if !stack <> [] then err ();
   !l

let printf (Format (fmt, fmt_s) : ('a, unit, t, f) format4) : 'a =
   let open CamlinternalFormat in
   make_printf (fun () acc -> printf_k fmt_s acc) () End_of_acc fmt


-- Alain

  reply	other threads:[~2014-07-01 16:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-01  9:59 Gabriel Kerneis
2014-07-01 14:15 ` Tianyi Cui
2014-07-01 14:39   ` Gabriel Kerneis
2014-07-01 15:27 ` Jeremie Dimino
2014-07-01 16:06   ` Alain Frisch [this message]
2014-07-02  9:27     ` Gabriel Kerneis
2014-07-02 13:34       ` Gabriel Scherer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53B2DC94.6050809@frisch.fr \
    --to=alain@frisch.fr \
    --cc=caml-list@inria.fr \
    --cc=gabriel@kerneis.info \
    --cc=jdimino@janestreet.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).