[wg-camlp4] Matching on concrete syntax (was: Re: Camlp4 uses)
Gabriel Scherer
gabriel.scherer at gmail.com
Fri Mar 29 13:46:47 GMT 2013
Would it be possible to use the extension mechanism itself for lightweight
quasiquotations?
I did a small experiment with -ppx recently (
http://gallium.inria.fr/blog/a-library-to-record-ocaml-backtraces/smartcatch_ppx.ml,
as a contribution to Jacques-Henri Jourdan's work on
http://gallium.inria.fr/blog/a-library-to-record-ocaml-backtraces/ ), and
frankly the absence of quasiquotations felt like a pain in the ass. Compare
the camlp4 part of the relevant code:
let add_debug_expr _loc patvar e =
<:expr<
let _ = ExceptionHandling.register $lid:patvar$ in
$e$
>>
with the Ast_rewriter equivalent (the recommended solution alongside -ppx
right now):
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)
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?
let add_register patvar body =
[%quote
let _ = ExceptionHandling.register [%anti patvar] in [%anti body]
]
I'm rather interested in getting ideas of how this actually would work and
fleshing it out.
(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.)
On Fri, Mar 29, 2013 at 2:04 PM, Alain Frisch <alain.frisch at lexifi.com>wrote:
> On 01/29/2013 05:22 PM, Alain Frisch wrote:
>
>> On 01/29/2013 04:37 PM, Xavier Clerc wrote:
>>
>>> However, during development,
>>> it was a time-saver to be able to easily express and experiment new
>>> ideas by manipulating "bits of the actual language". Camlp4 was kind
>>> enough to translate them for me into AST code which I had to check.
>>>
>>
>> What about having a tool (either stand-alone or part of the compilers)
>> which dumps the Parsetree representation of some code fragment in as
>> textual OCaml values (probably without locations)?
>>
>> So you can type your "model" as source code and obtain quickly the
>> Parsetree representation, copy/paste it into a nice pattern and replace
>> some parts with variables.
>>
>
> I've hacked a quick implementation of such a tool, reusing the generic
> value printer from the toplevel:
>
> http://caml.inria.fr/cgi-bin/**viewvc.cgi/ocaml/branches/**
> extension_points/tools/dump_**ast.ml?revision=HEAD&view=**markup<http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/branches/extension_points/tools/dump_ast.ml?revision=HEAD&view=markup>
>
> 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).
>
> Examples:
>
> $ ./ocamlast -w 50 -e "1 + x [@attr] * 2"
> {pexp_desc =
> Pexp_apply
> ({pexp_desc = Pexp_ident {txt = Lident "*"}},
> [("",
> {pexp_desc =
> Pexp_apply
> ({pexp_desc =
> Pexp_ident {txt = Lident "+"}},
> [("",
> {pexp_desc =
> Pexp_constant (Const_int 1)});
> ("",
> {pexp_desc =
> Pexp_ident {txt = Lident "x"}})]);
> pexp_attributes =
> [("attr",
> {pexp_desc =
> Pexp_construct ({txt = Lident "()"},
> None, false)})]});
> ("",
> {pexp_desc = Pexp_constant (Const_int 2)})])}
>
>
> $ ./ocamlast -w 50 -emptyattrs -t "int list * string"
> {ptyp_desc =
> Ptyp_tuple
> [{ptyp_desc =
> Ptyp_constr ({txt = Lident "list"},
> [{ptyp_desc =
> Ptyp_constr ({txt = Lident "int"}, []);
> ptyp_attributes = []}]);
> ptyp_attributes = []};
> {ptyp_desc =
> Ptyp_constr ({txt = Lident "string"}, []);
> ptyp_attributes = []}];
> ptyp_attributes = []}
>
>
> 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:
>
> http://caml.inria.fr/cgi-bin/**viewvc.cgi/ocaml/branches/**
> extension_points/parsing/ast_**helper.mli?revision=HEAD&view=**markup<http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/branches/extension_points/parsing/ast_helper.mli?revision=HEAD&view=markup>
>
> 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).
>
>
>
> Alain
> ______________________________**_________________
> wg-camlp4 mailing list
> wg-camlp4 at lists.ocaml.org
> http://lists.ocaml.org/**listinfo/wg-camlp4<http://lists.ocaml.org/listinfo/wg-camlp4>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ocaml.org/pipermail/wg-camlp4/attachments/20130329/467e1def/attachment.html>
More information about the wg-camlp4
mailing list