Most of my time this week was spent traveling and in meetings, but I did have a chance to work on the Clojurescript macro system that I have been working on.


Things didn't start too well for the system, since it would not run the simplest of tests written for it in the Clojurescript testing system. My test was a macro that would take a positive integer, recursively decrease it until it was zero, and then output the zero. (Clearly not the smartest macro in the world – it was just meant to test recursion.) However, I kept getting errors saying that the system didn't know how to test equality among numbers. This seemed strange until I realized that the extend-type call for numbers wasn't getting executed because it wasn't expanded into a def. (I had been executing all def calls, which defined all functions and variables, but nothing else.)

So I briefly flirted with executing a bunch of other special forms, including set! and deftype, but I could see that this would make things pretty unwieldy, and that the compiler would be doing a lot of confusing things, for example trying to execute a set! that was buried deep inside a function without being able to know anything about the locals that it was being set to.

That was clearly the way of madness, so I eventually decided to execute every special form that was at the top level. This worked really well, and the tests started passing.

I also added tests to make sure that the namespaces work as expected. You can use or require macros from other namespaces just like other functions.

What's not there (yet)

So far I have not added the &env and &form variables to macros. I expect that it will be necessary to add them at some point (and honestly not too hard). I know they are extremely useful in some projects like core.match, but that project has already been ported to Clojurescript (via Clojure macros), so it might make more sense to leave the large macros that need those facilities to Clojure.

Backquoted forms don't work as nicely as in Clojure. The reason is that we are using Clojure's reader, which qualifies backquoted symbols with their full namespace. Unfortunately, it doesn't know anything about Clojurescript namespaces, so expect to need to qualify symbols inside backquotes. This is an area where true reader macros inside Clojure would be really helpful, but we have to live with what we have.

One step closer

… to Clojure in Clojure. Clojurescript already has a reader and a compiler that can compile most of itself. The reader isn't totally complete – it doesn't have backquote working yet for example – but it is close. It recently got persistent vectors and persistent hash-maps. With macros added, all that's left for Clojure in Clojure is to finish up the reader and get rid of the calls to Java.

blog comments powered by Disqus