As a pet project, I’ve implemented an interpreter in Haskell for a small language that I’ve also designed. Before you definitely categorize me crazy, I’ve done it mostly to learn. So I have no pretension of coming up with the Next Big Language. And I’ve learned quite a bit about Haskell, about programming languages design and some more about interpreters, compilers and VMs. It’s actually amazing how much you learn by going a bit to the metal.

I’ve dubbed the language Witty. It’s strongly and dynamically typed, functional and encouraging a functional style (although not pure nor lazy), not particularly object-oriented (but something like CLOS could be supported) and somewhat homoiconic, permitting good macro support (Lisp-style and pattern-based). These are the main orientations, particularly with lambdas and macros, but I plan to add quite a few other features along the way. The main influences are, in that order: Scheme, Haskell and Javascript.

Witty is by no means finished, actually it’s closer to barely started. My biggest gripe right now is that it’s not functional enough. But I can already execute a few interesting things like the Fibonacci classic and enough to have a very simple Spec-style test framework. There are modules, exceptions, the classic data structures and of course macros and lambdas. It’s all a bit bare but it’s a good start I think. Here are a few code examples (the ^ symbol is equivalent to opening a parenthese and closing it at the end of the line, a bit like $ in Haskell):

> fact = lambda n ^ if (n == 1) 1 (n * fact (n – 1))
> fact 5

> macrox (unless `cond `body `contra?)  ^ if ((!) $cond) $body $contra
> unless false (print “awesome!”)

And here is a small test example:

describe “Map empty” (
it “should return true for an empty hash” (empty? {} == true)
it “should return false for a non-empty hash” (empty? {foo:1, bar:4} == false)

An interesting thing is that even == or ^ are implemented as macros. As you can see above, unless is also a macro.

I’ve decided to design my own pet language instead of implementing an existing one both because it was more fun (heh!) and because I had some ideas. There aren’t many dynamically-typed functional languages that support Lisp-style macros. Dylan might be close but I don’t like it for other reasons. My biggest surprise has been how hard syntax was to get right, even when it’s relatively minimal. I expected it to be hard but not that hard. I rewrote the grammar something like 6 or 8 times. Comparatively the interpreter is a piece of cake.

By implementing a non-pure programming language on top of Haskell, I was fearing I would end up banging my head against the wall. And I did a few times. But once you get past the steepest parts of the learning curve, it’s infinitely rewarding. And for quite a few things, it made the implementation much quicker because Haskell is so feature rich. For example I’ve added continuations to Witty in just a few evenings (3 I think) by snarfing Haskell ones. I know, I know, continuations support doesn’t often come up as a priority feature but I wanted to see if it would help implementing exceptions. And in the future, should I want to add software transactional memory or concurrency, it would be similarly easy. But before that, I should probably worry about file access…

I’ll probably write more posts about Witty but for a first I think that’s enough. All the source is in Github for your enjoyment. It’s definitely not ready for anything else than playing around but I’d be happy if others can learn something from it. You’ll need GHC should you want to build it and right now the tests are the best documentation.