Re: [abc-dev] Cflow extension and small problem with polyglot

From: Pavel Avgustinov <>
Date: Sat Aug 20 2005 - 12:00:16 BST


The reason for this is actually not Polyglot but our lexer.

I don't know how familiar you are with it. We use a stateful lexer to
allow us to recognise different keywords in different contexts. In
particular, we have the states YYINITIAL (which is essentially Java,
plus some special keywords like 'aspect' and 'pointcut'), ASPECTJ (used
for "proper" AspectJ code, with things like 'declare parents'), POINTCUT
(used for, obviously, pointcuts) and POINTCUTIFEXPR (which is kind of a
special case of YYINITIAL -- that state is used to lex the java fragment
in an if() pointcut. We can't use the 'proper' Java state since this
state is terminated by a matching closing ')', while YYINITIAL isn't.

There are various keywords that cause transitions between the states.

Now, the problem at hand: Integer literals are handled just after line
600 in aspectj.flex, with the line that your '2' should be matched by
being 605. However, if you scroll up, you'll find (line 513) that all
these lexemes are only defined for the states YYINITIAL, ASPECTJ and
POINTCUTIFEXPR. It seems that, since 'normal' pointcuts don't allow
numeric literals, our lexer doesn't recognise them in the POINTCUT
state, which it is in when it reads your cflowlevel(2,executerun()).

This is a little bit unfortunate, since our lexer extensibility
mechanism doesn't at the moment provide a way of adding new non-keyword
lexemes to states. I see two approaches one could take to fix this.
Either duplicate the .flex file and add the integer literal productions
to the POINTCUT state somewhere (this should definitely work, but has
the disadvantage of your extension using a duplicated file, which you'd
have to keep in synch with main abc manually), or try to fiddle the
contents of a cflowlevel() to be parsed in POINTCUTIFEXPR state. I'm not
entirely sure if something like "2, executerun()" is a syntactically
valid Java fragment, however, so that approach may not work with the
current syntax.. At least it'd be easy to make the lexer switch to
POINTCUTIFEXPR state (check how the "if" keyword is handled in
abc.main.AbcExtension). Taking that approach would allow an arbitrary
syntactically valid fragment of Java code as the parameter of
cflowlevel(), so you'd have to do some additional checks to make sure
it's the right format.

Briefly discussing this with Julian, he suggests that making cflowlevel
*bind* the level would be more "AspectJ-like", for good or bad. So
"cflowlevel(2, executerun())" would become "cflowlevel(i, executerun())
&& if(i == 2)". This would give you the 'greater-than' and 'less-than'
constructs for free.

Hope this is of some help.. If you'd like to discuss this further,
please feel free. :-)

- P

Bruno Harbulot wrote:

> Hello,
> Following my previous messages about the control flow pointcut, I have
> experimented a bit more with the cflow constructs, and I have come
> across another (minor) problem, with polyglot.
> I have tried to implement a cflowlevel(X,/Pointcut/) pointcut, which
> works like cflow, but only matches when the counter has the same value
> as X.
> Here is an example of code:
> public class Test {
> public void run(int counter) {
> System.out.println("Thread:
> "+Thread.currentThread().hashCode()+", counter: "+counter) ;
> if (counter>0) {
> counter-- ;
> run(counter) ;
> }
> }
> public static void main(String[] args) {
> Test t = new Test() ;
> ;
> }
> }
> public aspect TestTrace {
> pointcut executerun(): execution(void*)) ;
> pointcut callrun(): call(void*)) ;
> before(): callrun() && cflowlevel("2",executerun()) {
> System.out.println(" - Before callrun() &&
> cflowlevel(2,executerun())") ;
> }
> }
> Here is what it produces:
> Thread: 8187137, counter: 5
> Thread: 8187137, counter: 4
> - Before callrun() && cflowlevel(X,executerun())
> Thread: 8187137, counter: 3
> Thread: 8187137, counter: 2
> Thread: 8187137, counter: 1
> Thread: 8187137, counter: 0
> The problem I have with polyglot (I thing) is that it did not allow me
> to have an integer as the first parameter type for cflowlevel:
> {: Grm.parserTrace("CFLOWLEVEL pointcut");
> :}
> This version compiles fine, but then, when I try to write my pointcut
> like "callrun() && cflowlevel(2,executerun())" (with 2 as an integer
> literal), I get the following error:
> TestTrace.aj:9: Illegal character "2"
> TestTrace.aj:9: Syntax error.
> It works if I use a string literal as follows:
> {: Grm.parserTrace("CFLOWLEVEL pointcut");
> :}
> However, if I put a non-integer string, I get a NumberFormatException,
> and not a nice syntax error message.
> Should I do something specific to use INTEGER_LITERAL?
> Apart from this small detail, once again, abc has proven to be really
> extensible. The only problems I had were about the access modifiers:
> many classes or methods used in my extension did not belong to the
> original packages, and I had to change them to be public ("protected"
> did not always work, in particular in cases where it is originally used
> for allowing access from classes that are in the same package, but not
> subclasses.) For extensibility, it would probably be better to have
> almost everything declared as "public" in abc, since the Java visibility
> model is not really perfect and prevents the visibility from extensions
> that would be in other packages.
> I was only experimenting with abc about this cflowlevel. It works when
> the counter value is equal to the value specified in the pointcut, but
> there could be similar implementations using "greater than" and "less
> than". I have not really investigated the problems that could arise
> regarding the weaving order and the conflict with the original cflow and
> cflowbelow (and there are probably some bugs left). Any comments on such
> a construct?
> Best regards,
> Bruno.
Received on Sat Aug 20 12:00:41 2005

This archive was generated by hypermail 2.1.8 : Wed Aug 31 2005 - 23:50:08 BST