ppxlib icon indicating copy to clipboard operation
ppxlib copied to clipboard

Registering an attribute transformation

Open joelreymont opened this issue 9 months ago • 3 comments

Is there a better way to register an attribute transformation than this?

I'm trying to port the @pass bit and I'm stumped!

let[@pass Scheme0 => SchemeNoLet (* Declare the type of the pass*)] remove_let =
  [%passes (* Start writing the passes over each non-terminal. In this case, we only have [expr] *)
    let[@entry] rec expr = function (* [@entry] means that the pass function will take an entry and recurse from there *)
      | `Let (id, value [@r] (* [@r] = Recursively apply this pass *), body [@r]) -> (* Matches the Scheme0 let expression *)
        `Apply (`Lambda (id, body), value) (* Must be a SchemeNoLet-compatible AST *)
  ]

joelreymont avatar May 29 '25 14:05 joelreymont

Indeed, we don't have context free rules to rewrite nodes based on their attributes so yes, as of today, you'd have to register a whole AST transformation.

We don't encourage such syntax in ppx-es and usually prefer to use extension nodes to mark nodes that must be rewritten.

You'll probably be happy to hear about #574 though. This should add what you're looking if I understood it correctly. You can find some of our concerns with this approach in the review of the PR.

I suppose you're mostly trying to preserve a pre-existing syntax. Do you have a link to the project you're trying to port?

NathanReb avatar Jun 03 '25 08:06 NathanReb

I was trying to port Nanocaml and succeeded by replacing attributes with extensions.

Then I gave up because the design needs a major rethink.

I don't think it needs to store the the OCaml module AST in a global hash table, for example. It should be able to just operate on the AST itself.

joelreymont avatar Jun 03 '25 08:06 joelreymont

Ah right, it's a bit of special case, feel free to ignore my comment regarding syntax as that shouldn't be a concern for you.

NathanReb avatar Jun 03 '25 09:06 NathanReb