Ayende @ Rahien

Unnatural acts on source code

Multi file DSLs

imageWhile 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

Andy Pook
10/11/2007 11:07 AM by
Andy Pook

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?

Ayende Rahien
10/11/2007 01:08 PM by
Ayende Rahien

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

Craig Neuwirt
10/12/2007 12:39 PM by
Craig Neuwirt

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 ;^)

Ayende Rahien
10/12/2007 01:29 PM by
Ayende Rahien

Craig, that is a good reason :-)

Comments have been closed on this topic.