22 Jul 2006 crhodes   » (Master)

I just spent some time making anonymous classes work in SBCL. It turned out to be harder than I thought, so it might be worth mentioning some of the nasty details for posterity (or, alternatively, so that I can bask in the appreciation of my indomitable spirit).

The description "anonymous" applied to classes, in the terminology of the Art of the Metaobject Protocol, is in fact a misnomer, because in fact anonymous classes typically have names (that is, cl:class-name returns something), but not proper names. So, creating an anonymous class can be done with (make-instance 'standard-class :name 3), and class-name on this class would return 3; (find-class 3), however, would return an error by definition.

Regular ("nymous", if you will) classes are specified by AMOP to be created by calling the function ensure-class, which itself ends up calling ensure-class-using-class. At some point in these calls, (setf find-class) must be called, to arrange for the class to have a proper name; it must certainly be called before class finalization, because it is entirely reasonable for a MOP user to want to call find-class from within methods on finalize-inheritance. In SBCLs prior to those of a week ago, which finalize classes eagerly, we dealt with this requirement by setting find-class as soon as the class was created; this is obviously incompatible with anonymous classes.

So to support anonymous classes, while still allowing classes with proper names at class finalization time, we have to delay class finalization. That's fine; it's explicit in the MOP description that finalization can be as late as creating the first instance. But delaying finalization turned out to unleash a hydra, with new heads growing every time I fixed an assumption in the code. If classes are finalized as soon as possible, then other codepaths – such as discriminating function caches, the type system, and so on – must be updated to deal with as-yet-unfinalized classes. This ended up taking a long time: even though the final patch only touched some 300 lines of code or so, it's depressingly easy to get the code into a state where it doesn't boot (and that situation is hard to debug, given that much of the printing machinery depends on a working CLOS implementation...)

The good thing about having a moderately-extensive test suite (24kloc of tests for 150kloc of code) is that it catches a lot of mistakes when changing things, and also documents what is expected to work. (The downside, or possibly "another good thing", is that it is quite hard to satisfy all those constraints with a random walk through codespace, even if it's directed.)

Latest blog entries     Older blog entries

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!