prism icon indicating copy to clipboard operation
prism copied to clipboard

Modifying AST and generating source code

Open jmthomas opened this issue 10 months ago • 5 comments

Forgive my ignorance but I'm trying to use Prism to modify Ruby source (add nodes) and then regenerate the source to be interpreted. I'm using Prism.parse(text) and then implementing a Prism::Visitor to potentially modify the nodes as they are visited. I assume this is possible but I haven't really seen any examples of it. Finally I would like to 'unparse' the AST back into source code.

The Python equivalent is indeed unparse which is where I'm taking many of the ideas. They also have a NodeTransformer which is allowed to modify the nodes in the visit pattern. I don't see equivalents in Prism but perhaps you're always allowed to modify the nodes ... this is Ruby afterall.

Thanks for any help pointing me in the right direction!

jmthomas avatar Feb 16 '25 16:02 jmthomas

If it can't be done to generate the source, I don't require the generated source code as long as I can run the modified AST result. Something like eval the modified AST. Not sure if that is possible.

jmthomas avatar Feb 17 '25 18:02 jmthomas

@kddnewton Any insights on this? @Earlopain Any ideas?

jmthomas avatar Feb 22 '25 20:02 jmthomas

Not quite sure why you pinged me on this 😅 I guess because I worked on the parser translator here, and RuboCop would need something like this as well in the future. But right now I haven't invested too much time into thinking about how RuboCop would make use of prism without a middleman. No ideas from me, sorry

Earlopain avatar Feb 27 '25 07:02 Earlopain

@Earlopain thanks ... I was just looking for advice for someone knowledgeable about Prism to weigh in on whether this was even possible right now.

jmthomas avatar Feb 27 '25 15:02 jmthomas

@jmthomas Evenutally unparser will support prism see:

  • https://github.com/ruby/prism/issues/3553
  • https://github.com/mbj/unparser/pull/387
  • https://github.com/mbj/unparser/issues/385

This is done via the translation layer to the parser AST, but I plan to drop to native as soon I do not have to support 3.2 anymore.

mbj avatar Apr 18 '25 20:04 mbj

Closing this since it is more a question, but the answer is yes, you can use a visitor to modify the AST, or even build a new AST. And they use something unparser to generate the ruby code again.

rafaelfranca avatar Jul 16 '25 17:07 rafaelfranca

unparser depends on the parser gem which I think makes it rather undesirable in combination with prism. I haven't checked it out yet but somewhat doubt that using the native prism ast would even work with unparser. This is not such a big deal for folks that currently use one of the translation layers since they can just continue to use what they already use (be that unparser, Parser::TreeRewrite or something else). But when you use prism bare it is a bit of a bother.

Previously kddnewton expressed desire to add such an api to prism itself here: https://github.com/whitequark/parser/issues/1046#issuecomment-2491891823

Earlopain avatar Jul 16 '25 19:07 Earlopain

Reading that thread, https://github.com/whitequark/parser/issues/1046#issuecomment-2492526529 seems also relevant.

I think unparser should/could work, by parsing, mutating the Prism AST, applying the translation to parser AST, use unparser. Obviously not the most efficient though.

eregon avatar Jul 16 '25 20:07 eregon

I think unparser is probably what I'm looking for. Looks like they are waiting for a new release of Prism to incorporate a few fixes before they support Ruby 3.4 and beyond.

jmthomas avatar Jul 17 '25 00:07 jmthomas