In the FSE/NI paper we had the following example

jpi void buying(Item item, float price, 
                int amount, Customer cus)
	extends checkingOut;
	
aspect Discount {	
	void around checkingOut(Item item, float price, int amt, Customer cus) {
		int factor = cus.hasBirthday()? 0.95 : 1;
		proceed(item, price*factor, amt, cus);
	}
	void around buying(Item item, float price, 
                     int amt, Customer cus) {
		int factor = (amt > 10) ? 0.85 : 1; 
		nextadvice(item, price*factor, amt, cus);
	}
}

Here, nextadvice calls the checkingOut advice.

We observed the problem that this is assymetric: this way, one can apply the buying advice before the checkingOut advice but not the other way around.

Eric B. here proposes an alternative semantics, which is closer to AspectJ and executes pieces of advice in order of declaration. Consider this slightly modified code:

aspect Discount {	
	void around checkingOut(Item item, float price, int amt, Customer cus) {
		int factor = cus.hasBirthday()? 0.95 : 1;
		proceed(item, price*factor, amt, cus); //(1)
	}
	void around buying(Item item, float price,
                     int amt, Customer cus) {
		int factor = (amt > 10) ? 0.85 : 1; 
		proceed(item, price*factor, amt, cus); //(2)
	}
}

Here, we call proceed in both pieces of advice. nextadvice does not exist in this semantics. The proposed semantics of this code is as follows. First of all, we execute all pieces of advice in the order in which they are declared. Hence, if we have a checkingOut joinpoint, then the checkingOut advice will execute first. At the position marked (1), the semantics of proceed is such that we continue with the next declared matching piece of advice, i.e., in this case buying. The proceed marked (2) proceeds to the original joinpoint since no further matching advice follows.

Now consider the case in which we dispatch a buying joinpoint. In this case we only execute the second piece of advice.

Note that this design allows us to flexibly change the ordering in which the pieces of advice will apply. The following declaration would induce the inverse dispatch ordering:

aspect Discount {	
	void around buying(Item item, float price,
                     int amt, Customer cus) {
		int factor = (amt > 10) ? 0.85 : 1; 
		proceed(item, price*factor, amt, cus); 
	}
	void around checkingOut(Item item, float price, int amt, Customer cus) {
		int factor = cus.hasBirthday()? 0.95 : 1;
		proceed(item, price*factor, amt, cus); 
	}
}

Here, on a checkingOut joinpoint we would apply the buying advice first, then followed by the checkingOut advice, then followed by the original joinpoint.

Dispatch sequence across aspects

The above semantics based on ordering is problematic when multiple aspects advise the same joinpoint type hierarchies. Which advice should then execute first? In this case Eric B. proposes to resort to a declare precedence statement as in AspectJ. In this case, “declare precedence” would probably bind stronger than the ordering within a single advice; in other words, we would first execute all matching pieces of advice from the aspect with highest priority and then all matching pieces of advice from the next aspect (in the order declared there) and so on. Does that makes sense? I wonder…