Multi file DSLs
While a DSL can really cut down the amount of code that you need to write, putting everything in one file is not a good idea. But I like my DSLs to be script like, without the need for an explicit compilation step. I have thought about it for a while now, and yesterday ago Craig Neuwirt* asked how it can be done using Binsor.
My default language is Boo, obviously, which is a static, compiled language that pretends that it is dynamic and scriptish, giving the best of all worlds. One of the cool things about Boo is that you can reference an assembly by just doing this:
import System.Data.SqlClient from System.Data
This make it very easy to write scripts, because you just declare things and they will be automatically referenced, without needing to pass parameters to the script runner.
Now, I wanted to have some way to handle file inclusion as well. But Boo doesn't support this. This is not something that you can do in a method, or dynamic loading, you have to do this as part of the compilation process.
In a normal language, I would be left with building pre-processors, or doing heuristics to find all the relevant files that I want, or write an XML file that would detail which file I want to include. But Boo is not a normal language, it is a Super Language. It let me do what I want. And I wanted to have file references.
So I did.
I love Boo, I really do. The initial sample I started with was this. This is actually on the examples, what do you know. Then I thought about how I wanted to it, and I figured out that I can do this:
import file from anotherFile.boo
Boo allows me to modify the compiler object model (AST) at compilation, so I just detect all the imports for the namespace "file", and then I compile and reference that file. I can even do this:
import file from "~/config/anotherFile.boo"
Where ~ is translated to the AppDomain BaseDirectory.
You can find the code here, about 100 lines of code, out of which around 30 could be YAGNIed away. Wasn't very hard, and make me love Boo all over again, for what it allows me to do.
* Who doesn't blog, and a search for "Craig Neuwirt blog" brings back my blog :-) (hint)
Comments
New to Boo (and am loving it) but...
Doesn't doing it this way mean that you need to setup the compiler or interpreter yourself? ie you can't use booc, booi or booish as standard.
booish has a "load" verb which includes an external file. It would seem possible that you should be able to create a macro to achieve the same effect. I've come close (basically a rewrite of your compiler step as a macro. Can't quite get it to work (as it's pretty much the first thing I've done with Boo).
I think the failing with the way I'm doing it is that it won't be compiled as an assembly reference (as your would) but would be loaded dynamically. Probably fine for most purposes though.
Thoughts?
Andy,
actually, all you need is a booc -p:CustomerStep
But when we are talking about DSLs, we are already talking about setting up the compiler yourself.
Brail, BooBS, Rhino ETL, Binsor, etc - all do it this way
LoL
If I can learn your secret to time management, I might be able to squeeze in some blogging. I have 3 kids under the age of 4, and you would be surprised at the lengths I go to just to get keep my OSS effots going ;^)
Craig, that is a good reason :-)
Comment preview