As I wanted to obtain a deeper understanding on how code generation, DSLs and programming languages in general are related to each other I started to research. I found a lot of publications on DSLs from various authors and companies.
One of those authors is Martin Fowler who is writing a DSL book and has written a great article about what he calls Language Workbenches, a vision of an IDE which inherently operates with and on DSLs.
This article made me realize that configuration files actually are instantiations of domain specific languages. So we have been using DSLs for ages without being aware of that. It is a very natural way of providing abstract views. Continuing this path leads to the following new thought:
Assume an API which consists of a bunch of functions which, in order to do something, must be called in the right order with the right parameters. Emanating from my experience I think that the fewer Turing-completeness one needs in order to do the calls right the less complex and thus the better such an API is. Without being able to quantify Turing-completeness I think the same counts for DSLs. They are not Turing-complete by intention. Instead they are as primitive as possible because this is what makes them easy to understand and use.
For me, an API and a DSL are essentially two different ways of providing the same thing, namely an abstract interface to some functionality. So writing a configuration file for the Apache web server can be regarded as actually programming a web server using a very abstract language and a very mighty implementation of that language. In principle I see no difference between providing for example the server address by means of a DSL for configuration and passing this information to the constructor of an HTTPServer in a Python program.
What differs is the language which I use to specify what I want, the framework which defines and implements the domain of that language and the software which processes my specification and brings it into execution. What's the same is that both systems consist of those three parts. And in fact many more systems do so.
On that level command line options, linker instructions, C++ templates, libpcap filter rules, javadoc annotations, markup languages and programming languages are all the same, namely domain specific languages. For every single of those DSLs a grammar has been specified and a parser has been implemented. On top of that each of those DSLs has its own runtime with coresponding tool chains, debuggers and documentation. What a waste of time and what a hatchery for security bugs. Is there no way to improve this?
I think there must be. But I have no concrete imagination yet of how this should be done best. I need to investigate further.