<div dir="ltr"><div>Would it be possible to use the extension mechanism itself for lightweight quasiquotations?<br><br>I did a small experiment with -ppx recently ( <a href="http://gallium.inria.fr/blog/a-library-to-record-ocaml-backtraces/smartcatch_ppx.ml" target="_blank">http://gallium.inria.fr/blog/a-library-to-record-ocaml-backtraces/smartcatch_ppx.ml</a>, as a contribution to Jacques-Henri Jourdan's work on <a href="http://gallium.inria.fr/blog/a-library-to-record-ocaml-backtraces/" target="_blank">http://gallium.inria.fr/blog/a-library-to-record-ocaml-backtraces/</a> ), and frankly the absence of quasiquotations felt like a pain in the ass. Compare the camlp4 part of the relevant code:<br>
<br><pre> let add_debug_expr _loc patvar e =
<:expr<
let _ = ExceptionHandling.register $lid:patvar$ in
$e$
>><br></pre></div><div>with the Ast_rewriter equivalent (the recommended solution alongside -ppx right now):<br><pre>let add_register patvar body =
let open Ast_mapper in
let register_fun = Location.mknoloc (Longident.parse "ExceptionHandling.register") in
(* let _ = <register_fun> <patvar> in <body> *)
E.(let_ Nonrecursive
[P.any (), apply (ident register_fun) ["", ident patvar]]
body)<br></pre></div><div>There is a gap of readability, maintainability but also writability between the two approaches. I suspect that the Ast_mapper.E domain-specific language could be improved to reduce it, but I'm not sure quasiquotations are not the best long-term solution. But maybe we can have quasiquotations with the current extension mechanism?<br>
</div><pre>let add_register patvar body =
[%quote<br> let _ = ExceptionHandling.register [%anti patvar] in [%anti body]<br> ]<br></pre><div class="gmail_extra"><br></div><div class="gmail_extra">I'm rather interested in getting ideas of how this actually would work and fleshing it out.<br>
<br></div><div class="gmail_extra">(Note that the problem here is to have a convenient way to write little pieces of OCaml AST when you program AST-to-AST filters of any kind. This is a restricted use case as compared to Camlp4 quasiquotations conventions, that offer facilities for antiquotations inside foreign quotations implementing a completely different syntax. I used the latter in Macaque, and they are exposed to end-users, so user-friendliness of the antiquotation syntax was important. Here it's only for extension *writers*, so it's ok if it's *a bit* heavy.)<br>
</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 29, 2013 at 2:04 PM, Alain Frisch <span dir="ltr"><<a href="mailto:alain.frisch@lexifi.com" target="_blank">alain.frisch@lexifi.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>On 01/29/2013 05:22 PM, Alain Frisch wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On 01/29/2013 04:37 PM, Xavier Clerc wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
However, during development,<br>
it was a time-saver to be able to easily express and experiment new<br>
ideas by manipulating "bits of the actual language". Camlp4 was kind<br>
enough to translate them for me into AST code which I had to check.<br>
</blockquote>
<br>
What about having a tool (either stand-alone or part of the compilers)<br>
which dumps the Parsetree representation of some code fragment in as<br>
textual OCaml values (probably without locations)?<br>
<br>
So you can type your "model" as source code and obtain quickly the<br>
Parsetree representation, copy/paste it into a nice pattern and replace<br>
some parts with variables.<br>
</blockquote>
<br></div>
I've hacked a quick implementation of such a tool, reusing the generic value printer from the toplevel:<br>
<br>
<a href="http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/branches/extension_points/tools/dump_ast.ml?revision=HEAD&view=markup" target="_blank">http://caml.inria.fr/cgi-bin/<u></u>viewvc.cgi/ocaml/branches/<u></u>extension_points/tools/dump_<u></u>ast.ml?revision=HEAD&view=<u></u>markup</a><br>
<br>
It parses either command-line arguments (currently, as types, expressions or patterns) or external .ml/.mli files, and shows the internal Parsetree representation. By default, location and empty attribute fields are removed (they can be restored with command-line flags: -locs and -emptyattrs).<br>
<br>
Examples:<br>
<br>
$ ./ocamlast -w 50 -e "1 + x [@attr] * 2"<br>
{pexp_desc =<br>
Pexp_apply<br>
({pexp_desc = Pexp_ident {txt = Lident "*"}},<br>
[("",<br>
{pexp_desc =<br>
Pexp_apply<br>
({pexp_desc =<br>
Pexp_ident {txt = Lident "+"}},<br>
[("",<br>
{pexp_desc =<br>
Pexp_constant (Const_int 1)});<br>
("",<br>
{pexp_desc =<br>
Pexp_ident {txt = Lident "x"}})]);<br>
pexp_attributes =<br>
[("attr",<br>
{pexp_desc =<br>
Pexp_construct ({txt = Lident "()"},<br>
None, false)})]});<br>
("",<br>
{pexp_desc = Pexp_constant (Const_int 2)})])}<br>
<br>
<br>
$ ./ocamlast -w 50 -emptyattrs -t "int list * string"<br>
{ptyp_desc =<br>
Ptyp_tuple<br>
[{ptyp_desc =<br>
Ptyp_constr ({txt = Lident "list"},<br>
[{ptyp_desc =<br>
Ptyp_constr ({txt = Lident "int"}, []);<br>
ptyp_attributes = []}]);<br>
ptyp_attributes = []};<br>
{ptyp_desc =<br>
Ptyp_constr ({txt = Lident "string"}, []);<br>
ptyp_attributes = []}];<br>
ptyp_attributes = []}<br>
<br>
<br>
This should should simplify the learning curve of the Parsetree, and even allow quick copy/paste to write patterns/expressions on Parsetree. That said, creating Parsetree fragments manually is quite tedious, and I've created a module to make this easier:<br>
<br>
<a href="http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/branches/extension_points/parsing/ast_helper.mli?revision=HEAD&view=markup" target="_blank">http://caml.inria.fr/cgi-bin/<u></u>viewvc.cgi/ocaml/branches/<u></u>extension_points/parsing/ast_<u></u>helper.mli?revision=HEAD&view=<u></u>markup</a><br>
<br>
Currently, this module exposes "builder functions" which are very close to Parsetree constructors/records (making locations and attributes optional), but one can easily improve its interface (either by changing the existing functions, e.g. to use optional and labelled arguments, or by exposing other function to cover common cases).<div>
<div><br>
<br>
<br>
Alain<br>
______________________________<u></u>_________________<br>
wg-camlp4 mailing list<br>
<a href="mailto:wg-camlp4@lists.ocaml.org" target="_blank">wg-camlp4@lists.ocaml.org</a><br>
<a href="http://lists.ocaml.org/listinfo/wg-camlp4" target="_blank">http://lists.ocaml.org/<u></u>listinfo/wg-camlp4</a><br>
</div></div></blockquote></div><br></div></div>