From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 77A777F9BB for ; Tue, 1 Jul 2014 18:06:43 +0200 (CEST) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of alain@frisch.fr) identity=pra; client-ip=193.252.23.214; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="alain@frisch.fr"; x-sender="alain@frisch.fr"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of alain@frisch.fr) identity=mailfrom; client-ip=193.252.23.214; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="alain@frisch.fr"; x-sender="alain@frisch.fr"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@msa.smtpout.orange.fr) identity=helo; client-ip=193.252.23.214; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="alain@frisch.fr"; x-sender="postmaster@msa.smtpout.orange.fr"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AiwBAMLbslPB/BfWnGdsb2JhbABag1+DSMMTAYEjDwEBAQEBCAsJCRQohAMBAQUjBBFAARALDgoCAgUWCAMCAgkDAgECATQRBgEMAQUCAQEXiCusYZwbF4ErjUEzB4J3gUwBBJplhwmQPg X-IPAS-Result: AiwBAMLbslPB/BfWnGdsb2JhbABag1+DSMMTAYEjDwEBAQEBCAsJCRQohAMBAQUjBBFAARALDgoCAgUWCAMCAgkDAgECATQRBgEMAQUCAQEXiCusYZwbF4ErjUEzB4J3gUwBBJplhwmQPg X-IronPort-AV: E=Sophos;i="5.01,582,1400018400"; d="scan'208";a="83167184" Received: from msa05.smtpout.orange.fr (HELO msa.smtpout.orange.fr) ([193.252.23.214]) by mail2-smtp-roc.national.inria.fr with ESMTP; 01 Jul 2014 18:06:42 +0200 Received: from [192.168.1.133] ([92.151.101.107]) by mwinf5d20 with ME id M46h1o0052K1lZG0346hPt; Tue, 01 Jul 2014 18:06:42 +0200 X-ME-Helo: [192.168.1.133] X-ME-Auth: bGV4aWZpQHdhbmFkb28uZnI= X-ME-Date: Tue, 01 Jul 2014 18:06:42 +0200 X-ME-IP: 92.151.101.107 Message-ID: <53B2DC94.6050809@frisch.fr> Date: Tue, 01 Jul 2014 18:06:44 +0200 From: Alain Frisch User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 MIME-Version: 1.0 To: Jeremie Dimino , Gabriel Kerneis CC: "caml-list@inria.fr" References: <20140701095955.GE4120@kerneis.info> In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Caml-list] Extending Format strings On 07/01/2014 05:27 PM, Jeremie Dimino wrote: > On Tue, Jul 1, 2014 at 10:59 AM, Gabriel Kerneis > wrote: > > Dear all, > > in CIL , 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