It seems like there are only a few cases where existing macro use is not directly replaceable with something easier/better:
- X-Macros.
- Code snippets designed to be inlined into existing code.
Now, let's look at
why you need those.
The first is really for using the compiler for code generation (in this case to avoid repetition). The second is more often used for adding a little syntactic sugar.
For code generation, I'll take an example I currently have pending. I am trying to write a mini-RPC library that is a single .h file in C. Don't ask why, there is not a good answer :-)
But, to do that, I need to write macros that generate function stubs to marshal/unmarshal arguments. And, I would like those macros to look a lot like functions themselves to avoid mixing in any extra syntax.
So, RTTI would allow me to do that. But RTTI is heavy and requires quite a bit of overhead. If I can generate code at compile time, I can possibly work around that.
Now, maybe there is a way to do something about this. Looking around at other languages, I note that Java is now using annotations more and more and more. Perhaps (the following is not fully fleshed out) there is a way to hook into the parser with something like that. Suppose we allow you to do annotations:
@RPC
func remote_add_nums(a:int, b:int): int
And somewhere else you define a
compile-time function
@RPC that takes some sort of arguments. In the case of Java, you get a fair amount of information, but it is all handled by run-time libraries. In C2, this is not desirable.
I can see that you could, theoretically, have
@RPC be compiled and then run at compile time. I am not sure what the arguments should be. In the above example, there should probably be some additional arguments to
@RPC for the server etc. Passing the function information as strings is probably not ideal since we are trying to get away from uncontrolled string handling.
Is there a way to do this usefully? Exposing the AST seems like a problem since it would force the AST to become a fixed, external API.
Now, take the second of my major cases, syntactic sugar. I have some macros I use to help me visually see things like mutex-protected blocks
synchronized_block(my_mutex) {
... do some protected things...
}
That is not natively in C. It is just a couple of for loops and some C99 inline variable declaration magic in a macro. If you return from the middle of the block, you lose. But, it is much, much easier for me to see what is in the block, whether I remembered to close the block etc. I got rid of a lot of bugs in a couple of programs when I did this. Very handy.
I would really like to be able to introduce some things like this. Sure, this example may be bad because it should be built into the language anyway, but hopefully you get the idea.
Perhaps we can use something like this:
sugar synchronized_block(m:*mutex)=for(...) for(...)
I'm not very happy with that, but there are some possibilities of combining annotation/compile time functions and this.
Sorry this is not well thought out. I had a few ideas and wanted to throw them out there.
Best,
Kyle