Thursday, November 06, 2008

Advising Factor (Aspect Oriented Programming, if you're nasty)

I've been pretty busy the last couple of weeks with school, so I haven't been able to get any real (read: non-school related...I am not a fan of Verilog) programming done. So, the other day, I decided to try and implement something neat in Factor. After thinking about it for a bit, I decided to try to implement what is known as "advice" in Lisp and "aspects" in Java.

I had tried to do something similiar to this in Scheme a couple of years ago, but that was not pretty: Since functions in Scheme are just symbols bound to functions, I had to keep track of the advice to call around each function externally (e.g. in a globally-scoped table). The alternative was to redefine the function to add the advice directly into the body, which was even uglier, and didn't allow you to undefine advice. Gross. In Factor, however, this is made much, much, much easier by the fact that words are tuples. This allows me to easily annotate and add properties to words (and I do mean easily--the whole vocab is only fifty-six lines (plus 21 of docs and 63 of tests (more tests than code, yeah!))).

How it works

The implementation of advice is actually quite simple: When we first advise a function, we annotate it to call call-before, call-after, and call-around. These words look properties of the word (named before, after and around, respectively), which contain hash-tables of the given type of advice for the function and call them. The before and after type advice is quite easy to implement (just call a list of quotations, either before or after the main body (which, as Slava points out, really should be a macro or some such for performance reasons)), but around is a little trickier...But, I am very tired now and I have a calculus midterm tomorrow morning, so I'll write about that part sometime soon.

Oh, and if you're interested, you can grab my code from git://factorcode.org/git/jamesnvc