This is version 0.6.5 of AspectL. It is available for the following Common Lisp implementations:
- Allegro Common Lisp, tested under 6.2 Trial Edition and should work under 7.0
- CMU CL, Pierre Mai's experimental port to Mac OS X
- LispWorks for Macintosh, tested under Personal Edition 4.3r2 (4.3.7)
- OpenMCL, tested under 0.14.2-p1 (Darwin port)
- SBCL, tested under 0.8.15
The tests have all been performed on Mac OS X but I haven't used any platform specific libraries, so the code should work fine on other platforms as well. The initial version of AspectL (0.5) was developed with LispWorks, and subsequently ported to the other platforms. The code relies heavily on the CLOS MOP and has undergone some important revisions since 0.5, but has obviously stabilized by now. I am now pretty sure that it should run on most Common Lisp platforms that have a decent CLOS MOP implementation. Preliminary tests with GCL 2.6.3 have failed and I will wait for a hopefully more ANSI-compliant GCL 2.7. Some implementation-specific restrictions:
- Under Allegro Common Lisp, accessor methods generated by standard-class are optimized but cannot be switched back to non-optimized code on class reinitialization. This means that non-special slots cannot be turned into special slots on class reinitialization. I have reported this as a bug to Franz Inc. When they fix this, I will also be able to fix the reinitialization protocol.
- Under Allegro Common Lisp, defmethod does not accept more than one qualifier. This means that the :override qualifier of special-method-combination can only be used for primary methods. Again, I have reported this as a bug to Franz Inc. When they fix this, :override should also work for before/after/around methods without any further changes to AspectL.
- Special generic functions do not work on OpenMCL since it currently doesn't implement the generic function invocation protocol as specified in The Art of the Metaobject Protocol. This may change in the future.
There is currently no separate documentation for AspectL available, except for the HTML files of the website and the documentation provided in the source code. However, I have tried my best to describe all the important definitions in the source code in (hopefully) sufficient detail. I have also tried to create an Albert documentation of the definitions, but wasn't successful in making docbook do what I want and have stopped spending my time on this for the time being.
Installation
I have provided system definitions for ASDF (aspectl.asd) and the defsystems of Allegro Common Lisp (aspectl-system.cl) and LispWorks (defsys.lisp). If you don't know how to use a defsystem, load the following files in the given order (or better yet, learn how to use a defsystem!):
- al-packages.lisp
- lw-compat.lisp (not under LispWorks)
- al-clos-mop.lisp
- al-pointcuts.lisp
- al-mixins.lisp
- al-dynascope.lisp
- al-special-class.lisp
- al-special-function.lisp (not under OpenMCL)
There is a package :aspectl (nickname :al) that provides the exported symbols from all internal AspectL packages, and a package :aspectl-user (nickname :al-user) that you can use for experimenting with AspectL (similar to :common-lisp-user).
Changes in 0.6.5
- I have called FINALIZE-INHERITANCE after manual class creation only in a few Common Lisp implementations. However, the MOP specification suggests that it is better to generally do this. (Thanks to Bruna Haible for pointing this out.)
- My previous definition of DEFMETHOD* may break because the MOP specifies that ENSURE-GENERIC-FUNCTION must signal an error when an already existing function of that name is not an instance of STANDARD-GENERIC-FUNCTION. This is fixed by using the existing generic function in case the given name is FBOUNDP. (Thansk to Bruno Haible for spotting the bug.)
- The Creative Commons License has been replaced with an MIT-style license. See the copyright notice in the download for further information. (Thanks to René van Bevern for pointing out the problems with CCL - it is just not intended to be used for software.)
- The lw-compat package is now provided as a separate system.
Changes in 0.6.4
- Removed CREATE-METHOD from the AL.CLOS-MOP package. That utility function relied on two ingredients: 1) MAKE-METHOD-LAMBDA, as specified by AMOP. However, MAKE-METHOD-LAMBDA is not available in several Common Lisp implementations, and if it is available it usually doesn't work as expected. I have been able to use it successfully only in LispWorks. 2) ENCLOSE, a function that is not part of ANSI Common Lisp but was part of CLtL2. Again, it is available only in few Common Lisp implementations, but more importantly I have overestimated its power. Its purpose is to "enclose" a lambda expression (a list, not a closure object) in a given lexical environment. However, ENCLOSE is only specified to perform macroexpansions, and similar things, but "the consequences are undefined" if the lambda expression attempts to use variable or function definitions of that environment. That was what I actually have hoped for. Since it is very unlikely that any Common Lisp implementation currently provides such a functionality, the point to use ENCLOSE at all is moot. So essentially, the two major reasons to provide CREATE-METHOD have vanished. Instead, use (EVAL `(DEFMETHOD ...)) to create a method programmatically. That's what CREATE-METHOD has done in most Common Lisps anyway, but (EVAL `(DEFMETHOD ...)) avoids some useless overhead and is much better readable. Many thanks go to Duane Rettig and Steven M. Haflich for clarifying the issues concerning ENCLOSE in detail. See the comp.lang.lisp thread starting with message <cl0no9$qe2$1@f1node01.rhrz.uni-bonn.de> for more details.
Changes in 0.6.3
- Fixed two minor bugs in INITIALIZE-CLASS-METAOBJECT.
Changes in 0.6.2
- Special classes need a special default superclass in order to work. For convenience reasons, it is implicitly added to a class definition so that programmers don't need to worry about that default superclass. However, in previous versions of AspectL, I have made a few mistakes here: Forward referenced classes were not handled correctly, and under certain circumstances invalid class hierarchies were created. These mistakes are now fixed, thanks to a fruitful discussion in comp.lang.lisp with Marco Baringer, Bruno Haible, Simon Katz and Kenny Tilton. Special thanks go to Bruno Haible for insisting on leaving COMPUTE-CLASS-PRECEDENCE-LIST alone and to Simon Katz for the idea of how to handle forward referenced classes by fixing the list of direct superclasses after they have been changed to "real" classes. AspectL now also provides two functions INITIALIZE-CLASS-METAOBJECT and REINITIALIZE-CLASS-METAOBJECT in the AL.CLOS-MOP package that implements all the necessary machinery to make these things work and that you can reuse for your own metaclasses.
- LispWorks uses :default-initargs instead of :direct-default-initargs for the direct default initialization arguments of a class, contrary to what AMOP specifies. I have added the necessary conditionalization in al-mixins.lisp. Since I mainly use LispWorks, I have also erroneously used CLASS-DEFAULT-INITARGS instead of CLASS-DIRECT-DEFAULT-INITARGS. I have also fixed this.
- A few minor changes to internal class names and conditionalization code.
Changes in 0.6.1
Changes since 0.5
- Destructive mixins were not adaptable for new metaclasses. This could be fixed by the usual xyz-using-class technique employed in the MOP. The bug showed up in conjunction with special classes - the special slots were only "accidentally" handled correctly by destructive mixins in the cases I have tested, but not in all cases. See al-special-class.lisp for an example of how to add your own metaclasses to the destructive mixins framework. This bug was fixed in 0.5.2.
- Modified the class reinitalization code in al-special-class.lisp in order to make it work for Allegro Common Lisp.
- Modified all the names containing special-generic-function to contain special-function instead. (Tired of typing so many characters. ;)
- Heavily modified the implementation in al-special-function.lisp to make it work on other MOP implementations, including:
- removed the class root-dynamic-scope and merged it with the class dynamic
- removed special accessor methods - the implementation scheme I had in mind wouldn't have worked and I have postponed this to future versions of AspectL
- the class special-function is not an instance of funcallable-special-class anymore - this confused SBCL's MOP implemetation (and would probably confuse other MOPs as well)
- compute-discriminating-function is not used anymore to add the object representing dynamic scope to a special function's list of arguments - this didn't work in any MOP implementation except for the MOP in LispWorks. Instead, the define-special-function is added that requires the declaration of two function names - one for calling the function, the other for defining methods. The addition of another argument is now performed in the first of those two functions.
- other minor changes (see the read-time conditionalizations in the source code)
Acknowledgements
I am thankful to the following people who have contributed, directly or indirectly, important insights and fruitful ideas: Marco Baringer, Jeff Caldwell, Frode Vatvedt Fjeld, Steven M. Haflich, Bruna Haible, Simon Katz, Kaz Kylheku, Barry Margolin, Duane Rettig, Christophe Rhodes, Kevin M. Rosenberg, Dan Schmidt and Kenny Tilton.