Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
research:software:phantom [2012/05/24 15:54] – [Known Bugs] jfabryresearch:software:phantom [2013/09/24 05:16] jfabry
Line 1: Line 1:
 +====== PHANtom ======
  
 +PHANtom (PHaro Aspect laNguage) is a modern Aspect Language for Pharo Smalltalk. For more info, feel free to contact [[people:jfabry|Johan]]
 +
 +**NEWS:** 
 +  * We are starting work on a new version of PHANtom that will use the Opal compiler and/or the upcoming reflectivity framework.
 +  * [[http://doi.acm.org/10.1145/2166929.2166939|A demo on PHANtom]] was given at [[http://aosd.net/2012/|AOSD'12]]
 +  * The paper PHANtom: a Modern Aspect Language for Pharo Smalltalk has been accepted in the Wiley journal Software – Practice and Experience. It is an extended edition of the IWST paper, a preprint is available [[http://pleiad.dcc.uchile.cl/papers/2012/fabryAl-spe-phantom.pdf| online]]
 +  * The [[http://doi.acm.org/10.1145/2166929.2166939|research paper presenting PHANtom]] was accepted at the [[http://www.esug.org/wiki/pier/Conferences/2011/International-Workshop-on-Smalltalk-Technologies|International Workshop On Smalltalk Technologies]] (IWST) at the [[http://www.esug.org/wiki/pier/Conferences/2011|ESUG 2011 conference]]. 
 +
 +----
 +
 +
 +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:
 +
 +| AspectJ | Use of patterns to select targets |
 +| AspectS | Use of Method Wrappers to implement aspects in Smalltalk |
 +| Eos-U | Aspects are first class entities |
 +| Classpects | Aspects are first class entities |
 +| AspectScheme | Advice and pointcuts are first class entities |
 +
 +In addition to this, PHANtom has a number of advanced aspect language features:
 +  * when executing advice, the list of scheduled advice may be obtained and modified. This is inspired by the work on [[http://portal.acm.org/citation.cfm?doid=1408681.1408689|Dynamic AspectJ]] by Assaf and Noyé
 +  * reentrancy is managed through the use of membranes This is from the [[research:mascheme|membranes]] work of Tanter et. al. [[http://dx.doi.org/10.1145/2162010.2162014|published at FOAL 2012]].
 +  * deployment of aspects uses scoping strategies (planned). This is an implementation of the work on [[http://doi.acm.org/10.1145/1353482.1353503|scoping strategies]] by Tanter.
 +
 +The original implementation of PHANtom is the engineering thesis work of [[people:dgaldames|Daniel]], under supervision of [[people:jfabry|Johan]].
 +
 +===== Language Overview =====
 +
 +In 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.
 +==== Pointcuts ====
 +
 +A 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 category of the classes.
 +Example:
 +<code Smalltalk>
 + PhPointcut receivers: 'Foo'
 + selectors: 'bar:'
 + context: #(receiver sender arguments)
 + restrict: #(MyCategory).
 +</code>
 +
 +You can use AspectJ-style patterns too.
 +Example:
 +Foo and all its subclasses
 +<code Smalltalk>
 + PhPointcut receivers: 'Foo+'
 + selectors: 'bar'
 +</code>
 +All the classes that have "Foo" in their name:
 +<code Smalltalk>
 + PhPointcut receivers: '*Foo*'
 + selectors: 'bar:'.
 +</code>
 +You can also use combinations of the above:
 +<code Smalltalk>
 + PhPointcut receivers: #('Foo' 'Bar class' 'FooBar+')
 + selectors: #('open' 'close').
 +</code>
 +
 +Patterns on selectors are also allowed, where the underscore matches one keyword. For example, below matches ''bar:baz:quux:'', ''bar:foobar:quux:'' et cetera 
 +
 +<code Smalltalk>
 + PhPointcut receivers: '*Foo*'
 + selectors: 'bar:_:quux:'.
 +</code>
 +
 +Pointcuts can have run-time tests by specifying a block that gets passed a context object. This object contains the context values as exposed by the pointcut 
 +
 +<code Smalltalk>
 + PhPointcut receivers: '*Foo*'
 + selectors: 'bar:'
 + context: #(sender)
 + if: [:ctx| ctx sender = some_special_object]
 +</code>
 +
 +We also support cflow pointcuts, by sending an inCflowOf: or notInCflowOf: message to a pointcut, with a second pointcut as argument. This creates a new pointcut that matches if the receiver pointcut is in the cflow of, resp. not in the cflow of, the argument pointcut. For example, the below code creates a pointcut that matches if the send of bar: is in the cflow of the send of quux:.
 +
 +<code Smalltalk>
 + (PhPointcut receivers: '*Foo*' selectors: 'bar:')
 + inCflowOf: (PhPointcut receivers: '*Foo*' selectors: 'quux:').
 +</code>
 +
 +Lastly, 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.
 +<code Smalltalk>
 + PhPointcut 
 + receivers: (#any asParser plusGreedy: 'instanceVariableNames: ''bar''' asParser)
 + selectors: #any asParser.
 +</code>
 +
 +==== Ådvice ====
 +
 +An 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 ''#foo'' to the ''bar'' object before the join point indicated by the pointcut ''pc'' occurs.
 +<code Smalltalk>
 + PhAdvice before: pc send: #foo to: bar
 +</code>
 +
 +Alternatively, a block may also be used. It is however considered bad coding style, avoid it for larger applications.
 +<code Smalltalk>
 + PhAdvice pointcut: pc
 + advice: [:context | Transcript show: (context receiver asString);cr.]
 + type: #after.
 +</code>
 +
 +
 +==== Inter-Type Declarations ====
 +
 +PhClassModifier is used to add instance or class variables, and behavior to a class, in the spirit of intertype declarations of AspectJ. Different from AspectJ is that class modifiers take a pointcut to determine the class(es) that need(s) to be changed. The classes that are changed are those that define a method on which the pointcut statically matches.
 +
 +Example, for a pointcut stored in a variable named 'pc':
 +<code Smalltalk>
 + PhClassModifier on: pc addIV: 'bar'.
 + PhClassModifier on: pc addIM: 'bar
 + ^bar ifNil: [bar := 0]'.
 +</code>
 +
 +A PhClassModifier needs to be added to an aspect (by sending the aspect the ''addClassModifier:'' message) for it to take effect, which happens when the aspect is deployed.
 +
 +==== Aspect ====
 +
 +An 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.
 +
 +<code Smalltalk>
 + 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.
 +</code>
 +
 +===== Download =====
 +
 +To download PHANtom, you can either get it from [[http://ss3.gemstone.com/ss/Phantom.html|SqueakSource3]], or [[http://www.dcc.uchile.cl/~jfabry/PHANtom/Pt.zip|download a pre-built image]].
 +
 +To get PHANtom from the old SqueakSource, first download the configuration, by evaluating the following in a workspace:
 +
 +<code Smalltalk>
 +Gofer new
 +  squeaksource: 'Phantom';
 +  package: 'ConfigurationOfPhantom';
 +  load.
 +</code>
 +  
 +The latest stable version version of PHANtom is then installed by evaluating the following in a workspace
 +
 +<code Smalltalk>
 +(ConfigurationOfPhantom project version: #stable) load: 'ALL'.
 +</code>
 +
 +The latest development version (which are usually pretty stable as well) are installed by evaluating the following in a workspace
 +
 +<code Smalltalk>
 +(ConfigurationOfPhantom project version: #development) load: 'ALL'.
 +</code>
 +
 +
 +===== Tips and Known Bugs =====
 +
 +**Tip**: The Test Runner (and the entire unit test framework) does complicated things at the metalevel, which sadly do not combine nicely with PHANtom. As a result, unit tests for code with aspects can behave inconsistently, especially when fixing bad behavior through the test run infrastructure (i.e. putting a self halt somewhere in the test case and then run it from the runner of a menu item). The advice in those cases is to run the tests by manually calling the method from a workspace.
 +
 +**Tip**: If / when there are a number of aspects still around and you cannot easily uninstall them (e.g. you do not have a reference to them anymore), all aspects can be uninstalled by a do-it of the following: PhAspectWeaver uninstallAll. Alternatively, to obtain a list of installed aspects: PhAspectWeaver installedAspects 
 +
 +**Bug**: Join 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.