Footguns don't enable more possibilities other than the possibility to shoot yourself in the foot. Arbitrary control flow is pretty much the textbook example of that. It doesn't allow more expression or make it easier to express the same concepts, it makes it more difficult for the author, future readers, and tooling to understand what is being expressed in the first place. Not to say it isn't necessary for the implementation of languages on the hardware, just that the additional complexity of such a construct is better served by being generated from higher level syntax through automation like compilers or virtual machines.
As for the question of conversion to basic blocks, the question to me is at what point does your macro expansion turn into a compiler plugin or extension? I think the idea of hooking into the compiler at different points in the pipeline and expanding it on a per-project basis is really cool, and it's an old idea that's present in many LISPs. Racket and Scheme have extremely expressive macro systems that allow you to basically write a compiler. It'd be really interesting to have a language where the compiler/virtual machine had great hooks for extensions written by the author of a program being compiled, so they could do crazy things at progressive levels of granularity and unsafety. I think MLIR has some support for that, but it's more a target like LLVM than a language in its own right.
Comments
Footguns don't enable more possibilities other than the possibility to shoot yourself in the foot. Arbitrary control flow is pretty much the textbook example of that. It doesn't allow more expression or make it easier to express the same concepts, it makes it more difficult for the author, future readers, and tooling to understand what is being expressed in the first place. Not to say it isn't necessary for the implementation of languages on the hardware, just that the additional complexity of such a construct is better served by being generated from higher level syntax through automation like compilers or virtual machines.
As for the question of conversion to basic blocks, the question to me is at what point does your macro expansion turn into a compiler plugin or extension? I think the idea of hooking into the compiler at different points in the pipeline and expanding it on a per-project basis is really cool, and it's an old idea that's present in many LISPs. Racket and Scheme have extremely expressive macro systems that allow you to basically write a compiler. It'd be really interesting to have a language where the compiler/virtual machine had great hooks for extensions written by the author of a program being compiled, so they could do crazy things at progressive levels of granularity and unsafety. I think MLIR has some support for that, but it's more a target like LLVM than a language in its own right.