ocaml-ppx / ppx_tools

Tools for authors of ppx rewriters
MIT License
134 stars 39 forks source link

Add antiquotation for structure. #42

Closed paurkedal closed 8 years ago

paurkedal commented 8 years ago

This makes it more convenient to merge multiple generated items into a structure, e.g.:

[%str
  type t = int
  [%%s make_foo_helpers x]
  let foo = [%e make_foo_body x]
]

It's only supported in expression position, since patterns would be ambiguous.

alainfrisch commented 8 years ago

Is the syntax [%%s] (as in the comment or in the PR description) or [%s] (as a quick look at the code suggests)?

paurkedal commented 8 years ago

I would think it's [%%s] due to it's use in a structure, and dumpast tells me that's a Pstr_extension. Here is there actual code I used to test it

open Parsetree

let s =
  let three_four = [%str let three = 3 let four = 4] in
  Printast.structure 0 Format.std_formatter
  [%str
    let one = 1
    let two = 2
    [%%s three_four]
    let five = 5
    let six = 6
  ];

Am I missing something?

alainfrisch commented 8 years ago

Ah yes, of course, sorry.

alainfrisch commented 8 years ago

Could you rewrite the loop in a more direct style, with a single map-like traversal over the list (no reversal, no accumulator, a single function)? I don't think that lack of tail-recursion matters here (the default mapper uses List.map anyway).

paurkedal commented 8 years ago

I'll take a look in the evening and see how much I can simplify it. The main purpose of the reversal is to optimise the generate code: It turns the tail of the structure into a plain list construction, whereas everything that comes before a substitution must use cons instead. At least if we skip the list-optimisation it should be possible to use a single fold with no reversals.

alainfrisch commented 8 years ago

list simply folds cons, so the generated code would be the same I think.

paurkedal commented 8 years ago

You're right, and that simplified the code a lot! I'll fix the signature PR accordingly.

alainfrisch commented 8 years ago

Thanks!

(For the records, an alternative implementation of [%%s ...] is to encode it as include struct ... end, which is a single structure item itself; but although semantically equivalent, the compiler might behave differently, so it's better to flatten the structure.)