|
Table of Contents
PHANtomPHANtom (PHaro Aspect laNguage) is a modern Aspect Language for Pharo Smalltalk. NEWS: The research paper presenting PHANtom was accepted at the International Workshop On Smalltalk Technologies at the ESUG 2011 conference. A preprint is available online: phantom-iwst.pdf. The design of PHANtom is inspired by various aspect languages like AspectJ, AspectS, Eos-U Classpects and AspectScheme. We took elements from each of these as follows:
In addition to this, PHANtom has a number of advanced aspect language features:
PHANtom is the engineering thesis work of Daniel, under supervision of Johan. Language OverviewIn PHANtom, aspects, pointcuts and advices are first-class objects. The joinpoint model is based on message reception, so to specify a pointcut you need a message, and the object that receives the message. The main classes of PHANtom are: PhPointcut PhAdvice PhAspect PhClassModifier PhContext We discuss them here in this order. Note that PHANtom does not have its own syntax, instead aspects are constructed using standard Smalltalk code. A separate syntax for PHANtom code is currently under consideration. PointcutsA pointcut is modeled by the PhPointcut class. You can specify the receptors of the message, the selectors, and optionally the context that will be exposed to the advice (receiver, arguments, sender, selector, proceed), and also optionally the catergory of the classes. Example: PhPointcut receivers: 'Foo' selectors: 'bar:' context: #(receiver sender arguments) restrict: #(MyCategory). You can use AspectJ-style patterns too. Example: Foo and all its subclasses PhPointcut receivers: 'Foo+' selectors: 'bar' All the classes that have “Foo” in their name: PhPointcut receivers: '*Foo*' selectors: 'bar:'. You can also use combinations of the above: PhPointcut receivers: #('Foo' 'Bar class' 'FooBar+') selectors: #('open' 'close').
Patterns on selectors are also allowed, where the underscore matches one keyword. For example, below matches PhPointcut receivers: '*Foo*' selectors: 'bar:_:quux:'. You can use your own PetitParser parser, and select all the classes whose class definition matches the parsers. For example, all the classes that have an instance variable named: 'bar', and all their selectors. PhPointcut receivers: (#any asParser plusGreedy: 'instanceVariableNames: ''bar''' asParser) selectors: #any asParser. ÅdviceAn Advice is modeled by PhAdvice, a PhAdvice is of a given type (before, after, around) and specifies a pointcut and advice.
A selector and object are used to specify the behavior. For example, the following sends the message PhAdvice before: pc send: #foo to: bar Alternatively, a block may also be used. It is however considered bad coding style, avoid it for larger applications. PhAdvice pointcut: pc advice: [:context | Transcript show: (context receiver asString);cr.] type: #after. Inter-Type DeclarationsPhClassModifier is used to add instance or class variables, and behavior to a class, in the spirit of intertype declarations of AspectJ. Example: PhClassModifier on: 'Foo' addIV: 'bar'. PhClassModifier on: 'Foo' addIM: 'bar ^bar ifNil: [bar := 0]'.
A PhClassModifier needs to be added to an aspect (by sending the aspect the AspectAn aspect is modeled by the PhAspect class. On a PhAspect instance you can add PhAdvice and PhClassModifier instances. This PhAspect instance then can be installed on the system (and later uninstalled when no longer needed). Example: You want to print to the Transcript every time a SystemWindow or any of its subclasses are moved. You also want to know what window moved, and the point to where it was moved. asp := PhAspect new add: (PhAdvice pointcut: (PhPointcut receivers: 'SystemWindow+' selectors: 'position:' context: #(receiver arguments)) advice: [:context | Transcript show: context receiver. Transcript show: ' moved to: '. Transcript show: context arguments; cr.] type: #after). asp install. DownloadTo download PHANtom, first download the configuration, by evaluating the following in a workspace: Gofer new squeaksource: 'Phantom'; package: 'ConfigurationOfPhantom'; load. The latest stable version version of PHANtom is then installed by evaluating the following in a workspace (ConfigurationOfPhantom project version: #stable) load: 'ALL'. The latest development version (which are usually pretty stable as well) are installed by evaluating the following in a workspace (ConfigurationOfPhantom project version: #development) load: 'ALL'. Known BugsJoin points generated by the infrastructure of PHANtom are still captured by the aspects themselves. This may lead to infinite loops, e.g. when aspects intercept messages sent to collections. If you only use pointcuts that match on classes of your own implementation you will not encounter this bug. | ||||||||||