In my previous post I introduced the horn package manager open source project that I have been contributing to and the fact that I am blogging these posts to help me prepare for my talk at the Dsl DevCon conference.
In my previous post, I mentioned that we would be basing the the horn package manager on the excellent gentoo portage package management system. At the heart of the portage system is the concept of ebuilds that contain information that allow the portage system to both compile and install software packages.
Our first step in the evolution of the horn was to author the Dsl of build and metadata instructions that we would model on portage's ebuild scripts.
I suppose the first question that a would be DSL author will face is, do I create an internal Dsl or an external Dsl? At the time of horn's inception, oslo had not been previewed and not wanting to get downd and dirty with something like yak or antlr an internal Dsl was the right choice. Even if oslo had been available, I probably would have gone with an internal Dsl anyway. I don't really get a chance to mess around with alternative languages in my day job so this was a chance to do some fun experimentation.
I have been reading Ayende's blog for a few years now and it was through this blog that I first heard the term ALT.NET. The blog alone has been a great source of new and interesting practices that I would have otherwise been oblivious to. Ayende is also the driving force behind the excellent Rhino tools. There are a multitude of excellent bits and pieces here that can help with common less granular programming tasks to full blown ETL transformations. Even getting familiar with the code base has been been enlightening and educational. I use parts of the excellent Rhino stack and it is the pain of upgrading such open source pacakages as Rhino that horn is trying to alleviate.
Rhino has a number of DSLs that are used to help give a higher level of abstraction to certain tasks. There is Binsor which is a DSL for initialising the Castle Windsor IoC container and Rhino.ETL which uses a DSL syntax to express transformations in an ETL workflow. In both cases the DSLs are internal DSLs with boo used as the host language. I have experience of using both these projects so the choice of our internal Dsl was an obvious one. I had also recently read the excellent Building Domain Specific Languages in Boo on a recent long haul flight from the UK to Vietnam. I will be paraphrasing from the aforementioned book, so it is only fair I mention both the tome and the author.
Boo is an object oriented language for the Common Language Infrastructure with a python inspired syntax and a special focus on language and compiler extensibility.
When I fist chose boo as the host language of our Dsl, I was not convinced of ironruby's maturity. Later, when I show how you can implement the same Dsl using ironruby, you will see this was wrong. I still think that boo offers more with respect to DSLs but this could be down to my limited experience of both languages.
I must take this time to both introduce boo to those in the audience who are unfamiliar with it and to speak gushingly about it's elegance. I see Boo as a slightly schizophrenic CLR language. I describe it this way because boo is a static language with many qualities that are more associated with dynamic languages.
Boo has the following characteristics that make it an ideal language for hosting DSLs:
- Significant Whitespace - Boo uses a colon to initiate a control block and the level of indentation to indicate the scope. When I came to experiment with rewriting the DSL in ironruby as we will see later, I found the do and end control block markers almost impalatable after working with boo.
- Type Inference and automatic type casting - You can liken this to C#'s var keyword but of course without the var.
- Duck Typing - You can by implementing the excellently named IQuackFu interface ask the compiler to relax the strong typing constraints and provide an experience that is very similar to constructs like method_missing in Ruby.
- Compiler Extensibility
As I will show later, boo has some stunning compiler extensibility points that set it truly apart from other languages. Meta methods and macro expansions are 2 techniques that can get you up and running very quickly with your own custom DSL.
In my next post, we will briefly list the purpose of the horn Dsl.
If any of this is of interest to you then please join the Horn user group for updates or check out the source here.