Search code examples
ocamlppx

Metaquot examples or documentation to generate code


I'm trying to write simple rewriters with ppxlib to get an idea of how to do more complex things.

I'm currently struggling with metaquot. The documenation I found is this one but it just touches the surface and there's nothing in the .ml or .mli files that help understand the possibilities.

I'm trying to transform

let x = <expr> 

into

let x = 
  let res = <expr> in 
  res

I dumped both ast:

[{pstr_desc =
   Pstr_value (Nonrecursive,
    [{pvb_pat = {ppat_desc = Ppat_var {txt = "x"}; ppat_loc_stack = []};
      pvb_expr =
       {pexp_desc = Pexp_constant (Pconst_integer ("23", None));
        pexp_loc_stack = []}}])}]

and

[{pstr_desc =
   Pstr_value (Nonrecursive,
    [{pvb_pat = {ppat_desc = Ppat_var {txt = "x"}; ppat_loc_stack = []};
      pvb_expr =
       {pexp_desc =
         Pexp_let (Nonrecursive,
          [{pvb_pat =
             {ppat_desc = Ppat_var {txt = "res"}; ppat_loc_stack = []};
            pvb_expr =
             {pexp_desc = Pexp_constant (Pconst_integer ("23", None));
              pexp_loc_stack = []}}],
          {pexp_desc = Pexp_ident {txt = Lident "res"}; pexp_loc_stack = []});
        pexp_loc_stack = []}}])}]

So I need to transform a Pexp_constant ... into a Pexp_let ...

I came up with this:

let wrap_with_fun_call expr loc _key =
  let open Ppxlib.Ast_helper in
  [%expr
    [%e
      Exp.let_ Nonrecursive
        [
          ( Exp.ident
            @@ { txt = Parse.longident (Lexing.from_string "res"); loc },
            expr );
        ]
        (Exp.ident @@ { txt = Parse.longident (Lexing.from_string "res"); loc })]]

But the first Exp.ident @@ ... doesn't have the proper type and I'm stuck. I can't find anything in ppxlib that generates value_binding list and can't find good examples on-line or documentation that would explain what the metaquot possibilities are (except the documentation I linked before)

Are there some good resources to understand better what's possible and how to do it?

There's surely an easy way to do what I want (as it is relatively simple) with metaquot but I couldn't find how.


Solution

  • So the answer was simply:

    [%expr                  
      let res = [%e expr] in
      res]
    

    What confused me is that I didn't write the in res part and the error message was misleading (eval expected)