I know I can use macros to generate new code. Is it also possible to modify the AST of existing definitions? Let's say for example I have imported a module defining the following proc:
proc add*(x,y: int): int =
x+y
and I like to proxy (intercept) all calls add(x,y)
such that the applied operation is printed. Hence, I'd like to make something like a macro onbefore(add, action)
, which modifies the add proc to e.g. this (please have in mind that this is just a nonsense example to show what I mean):
proc add*(x,y: int): int =
echo $x & " + " & $y
x+y
I know, at least for this trivial case, it should be possible to use a term rewriting template for this (though I could not yet get this running without recursive replacement, when calling the original proc in the template), but the general question is, if I even can pass the existing AST for the original proc to a macro which then applies arbitrary modifications to it?
No, that's not supported. You can implement it as a compiler plugin but you need to ensure that no codegen phase starts before your plugin did its transformation which is kind of hard to ensure with the current pipelined architecture in the compiler.
It's also not a wise thing to attempt, it breaks any kind of modularity and when used for debugging produces an overwhelming mess to dig through. :-)
Yes I know you could do much evil with this ;)
In my company we use a java framework which heavily uses bytecode manipulation to extend and modify user-defined classes. There are both, situations where you scratch your head in debugging to find out where the hell the intercepting code of your intended direct method call comes from, but also situations where you are just thankful about all the "magic" the framework does for you and the lack of boilerplate code. (Of course, I'm aware that Java bytecode manipulation is something completely different, because it happens at runtime).
Regarding your hint on doing it with a compiler plugin: well let's see if I become expert enough to touch things like this in a year or two from now on ;)
Until then I'll stick to more straight forward usage of the language...