Sure, I acknowledged that in my original post. I just said that it didn't have to be done that way.
> It's basically just manually combining the entire program into one function to get a version of unconstrained goto.
You really only need to combine those functions in question, and common lisp already has a pretty unconstrained goto already. Worst case, if you're willing to deal with the code bloat, you could copy the function definitions of the functions in question into each function as it's compiled (you'd have to defer macro expansion for n-1 of the functions though until runtime, or conditionally trigger re-compilation as each one is compiled). Probably would be a big pain though.
> It isn't a macro in the traditional lisp-sense of the word, more of a compiler for a new programming language that uses lisp as a host.
I mean, isn't making a dsl out of lisp macros rather traditional? That's how the loop construct began. The CLOS/Metaobject protocol also started out as 3rd party packaged, and they're also absolute beasts.
But, like, that's kinda the point of lisp. You can add your own syntactic abstractions to the language. Adding things to the language is part of the language. Is the argument here that those dsls aren't really lisp? How about the dsls that made it into some of the standards?
> it doesn't have many of the properties that are important in macros. It is not defined in a composable way, and it needs deep integration with the language runtime.
I'm not entirely sure where you got these requirements for macros, but I've never heard them. Admittedly, I've spent most of my time in Common Lisp and playing around with some of its ancestors. Maybe this is the case in some of the more scheme derived languages with hygenic macro-systems? I haven't really played around with them that much aside from a semester of scheme way back in the day in college.
Also, you might be able to get around the language runtime integration by hooking into the reader, but that would probably require making a meta-compiler (or at least keeping track of the symbol trees of everything that you've compiled so far). Would be a lot more portable than the thing I'm thinking of though.
> So if two packages tried to use different recursion macros, they would likely be incompatible.
With the implementation I have in my head, I think you could re-write the ones in the other package with the recursion method that the last one that gets compiled uses, but this would probably open up even more of a can of worms.
I agree that this is a good reason to do it as a language feature instead of as a macro, but not that it's impossible to do as a macro.