Match context in PPX rewriter

Hello everyone,

I am currently working on a ppx rewriter, my rule is attached to structured item. I was wondering if there was a way to retrieve information on that context ?

let expand ~ctxt e =
  ..

let my_rule =
  Extension.V3.declare_inline "my_ppx"
  Extension.Context.structure_item
  <payload>
  expand

where ctxt in expand has type:

type Expansion_Context.Extension.t =
 { extension_point_loc : Location.t ; base : Base.t }

(* with Base.t *)
type Base.t =
    { tool_name : string ;
      code_path : Code_path.t ; 
      input_name : string }

In a example:

let add x y = x + y
[%%my_pbt <payload>]

My goal would be to have access to fields such as [add x y] or [x + y]. But I have no idea at this point if it’s possible ?

1 Like

Hi @vch9.

Firstly, it’s worth noting that Ppxlib is expressive enough to handle any AST → AST transformation you can dream up (via Driver.register_transformation if needbe). It’s just a question of whether your use-case fits into any of the “simpler” APIs that Ppxlib provides.

If your goal is to attach metadata to a structure item, consider using attributes rather than extension points ([@@my_pbt <payload>] rather than [%%my_pbt <payload>]). At the syntax level, item extension points (with %%) are not “attached” to anything but sit inside the parent structure / signature as independent items. So the syntax you describe will look at the AST level more like the following:

(* List of four structure items: *)

let add x y = x + y

[%%my_pbt <payload>]

let sub x y = x + y

[%%my_pbt <payload>]

… and a tool like OCamlformat will format it as such. Item attributes (@@) are actually attached to specific items, and so it’s probably easier to get Ppxlib to reflect your intended interpretation using these.

Unfortunately, it seems Context_free.Rule is missing the exact function you’d need, so you’ll probably want to use Ast_traverse.map with a hand-written method for transforming items with your attribute. You can then pass the #structure method to Driver.register_transformation.

Hope this helps!

Definitely helps !

Attributes seems more suitable for my purpose :slight_smile:
I’ll also look into Ast_traverse.map, thanks for the pointer !

1 Like