| I've been thinking similar thoughts recently since I've been exploring metaprogramming in Scala and how it can be extended to beyond the simplistic hygenic model it currently supports. What I recently realized is that while compilers in the standard perspective process a language into an AST, do some transformations, and then output some kind of executable, from another perspective they are really no different than interpreters for a DSL. There tends to be this big divide between what we call a compiler and what we call an interpreter. And we classify languages as being either interpreted or compiled. But what I realized, as I'm sure many others have before me, is that that distinction is very thin. What I mean is this: from a certain perspective a compiler is really just an interpreter for the meta language that encodes and hosts the compiled language. The meta-language directs the compiler, generally via statements, to synthesize blocks of code, create classes with particular shapes, and eventually write out certain files. These meta-languages don't support functions, or control flow, or variables, in fact they are entirely declarative languages. And yet they are the same as the normal language being compiled. To a certain degree I think the biphasic model captures this distinction well. Our execution/compilation models for languages don't tend to capture and differentiate interpreter+script from os+compiled-binary very well. Or where they do they tend to make metaprogramming very difficult. I think finding a way to unify those notions will help languages if and when they add support for metaprogramming. |
Even hardware is, at some point, "programmed" by someone to behave a certain way.