Feature request: macro to pass code to command

I know there is a macro method to call out to a system command

https://crystal-lang.org/api/0.32.1/Crystal/Macros.html#system(command):MacroId-instance-method

It would be interesting to me, at least from an curiosity perspective, to be able to pass an AST or a “string block of code” to that command so it could return something and effectively rewrite existing crystal code. Just a thought/idea. Sorry I know I’ve requested it before LOL.

Cheers!

You can already do that. Pass a string representation of the ast to the macro, let the macro parse it, transform it, return it, and then you paste the result into the program.

Nice. It’s possible to pass the string as a parameter to the system command? Examples would be wonderful, thanks, I’m not experienced with macros…

Sure!

# foo.cr
macro foo(ast)
  {{ run "./bar", ast }}
  {% debug %}
end

foo def add(x, y)
  x + y
end

p add(2, 3)
# bar.cr
require "compiler/crystal/syntax"

include Crystal

code = ARGV[0]
nodes = Parser.parse(code)

a_def = nodes.as(Def)
a_def.body = Call.new(Var.new("x"), "*", Var.new("y"))

puts a_def.to_s

So we pass a def to the macro, we get it on bar (as code), we parse it and then modify the body to do a multiplication instead of an addition.

If you want to modify code in a more generic way you probably want to use a Crystal::Transformer.

I don’t know what use cases this has, but it’s possible.

It’s a bit slow to compile the first time but subsequent times should be faster.

Awesome, thanks!