towards typesafe join points for modular reasoning in
play

Towards Typesafe Join Points for Modular Reasoning in - PowerPoint PPT Presentation

Towards Typesafe Join Points for Modular Reasoning in Aspect-Oriented Programs Eric Bodden joint work with Milton Inostroza, ric Tanter


  1. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { System.out.println(“seed was:”+theSeed); return monteCarlo(theSeed); }(seed); return result; } jpi int JP(long s); int around JP (long mySeed) { return proceed(0); } 20

  2. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { System.out.println(“seed was:”+theSeed); return monteCarlo(theSeed); }(seed); return result; } jpi int JP(long s); int around JP (long mySeed) { return proceed(0); } 20

  3. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { System.out.println(“seed was:”+theSeed); return monteCarlo(theSeed); }(seed); return result; } jpi int JP(long s); int around JP (long mySeed) { return proceed(0); } 20

  4. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { System.out.println(“seed was:”+theSeed); return monteCarlo(theSeed); }(seed); return result; } jpi int JP(long s); int around JP (long mySeed) { return proceed(0); } 20

  5. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { seed==<time> System.out.println(“seed was:”+theSeed); theSeed==0 return monteCarlo(theSeed); }(seed); return result; } jpi int JP(long s); int around JP (long mySeed) { return proceed(0); } 20

  6. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { seed==<time> System.out.println(“seed was:”+theSeed); theSeed==0 return monteCarlo(theSeed); }(seed); return result; } jpi int JP(long s); int around JP (long mySeed) { return proceed(0); } 20

  7. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { seed==<time> System.out.println(“seed was:”+theSeed); theSeed==0 return monteCarlo(theSeed); }(seed); return result; } jpi int JP(long s); int around JP (long mySeed) { return proceed(0); } 20

  8. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { System.out.println(“seed was:”+theSeed); return monteCarlo(theSeed); }(seed); result==??? return result; } jpi int JP(long s); int around JP (long mySeed) { new Thread() { public void run() { proceed(mySeed); } }.start(); } 20

  9. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { System.out.println(“seed was:”+theSeed); return monteCarlo(theSeed); }(seed); result==??? return result; } jpi int JP(long s); int around JP (long mySeed) { CJPs are new Thread() { public void run() { expressions, proceed(mySeed); } not statements! }.start(); } 20

  10. int monteCarloAlg() { long seed = System.currentTimeMillis(); int result; result = exhibit JP(long theSeed) { System.out.println(“seed was:”+theSeed); return monteCarlo(theSeed); }(seed); result==42 return result; } jpi int JP(long s); int around JP (long mySeed) { CJPs are new Thread() { public void run() { expressions, proceed(mySeed); } not statements! }.start(); return 42; } 20

  11. Closure joinpoints: aspect side JPIs, as before jpi int JP(long s); advice directly int around JP(long seed) { refers to that return proceed(0); } joinpoint type no pointcuts required 21

  12. Closure joinpoints: base-code side reference to jpi int JP(long s); same JPI base code result = exhibit JP(long theSeed) { println(“seed was:”+theSeed); exhibits joinpoint return monteCarlo(theSeed); as call to closure }(seed); 22

  13. Variable-access rules class C { Field f; void foo(Param fp) { Local l; final Local L; exhibit JP(Param cp) { }(..); } } 23

  14. Variable-access rules class C { Field f; void foo(Param fp) { Local l; final Local L; exhibit JP(Param cp) { f = null; }(..); } } May read and write fields 23

  15. Variable-access rules class C { Field f; void foo(Param fp) { Local l; final Local L; exhibit JP(Param cp) { println(cp); }(..); } } May read (and write) closure parameters 23

  16. Variable-access rules class C { Field f; void foo(Param fp) { Local l; final Local L; exhibit JP(Param cp) { println(L); }(..); } } May read final locals 23

  17. Variable-access rules class C { Field f; X void foo(Param fp) { Local l; X final Local L; exhibit JP(Param cp) { println(l); println(fp); }(..); } } May NOT access non-final locals 23

  18. Control-flow rules class C { void foo() { for(int i=0;i<5;i++) { exhibit JP(){ }(); println(i); } } } 24

  19. Control-flow rules class C { void foo() { for(int i=0;i<5;i++) { exhibit JP(){ return; }(); println(i); } } } 24

  20. Control-flow rules class C { void foo() { for(int i=0;i<5;i++) { exhibit JP(){ return; }(); println(i); } } } “upward FUNARG problem” void around JP() { new Thread() { (Weizenbaum 1968, public void run() { Moses 1970) proceed(); } }.start(); } 24

  21. Control-flow rules class C { prints: void foo() { for(int i=0;i<5;i++) { 1 exhibit JP(){ 2 return; 3 }(); 4 println(i); 5 } } } break / continue / return always bind to closure, not to declaring method! 24

  22. Control-flow rules class C { void foo() { for(int i=0;i<5;i++) { exhibit JP(){ break; }(); println(i); } } } break / continue / return always bind to closure, not to declaring method! 24

  23. Control-flow rules class C { void foo() { for(int i=0;i<5;i++) { exhibit JP(){ continue; }(); println(i); } } } break / continue / return always bind to closure, not to declaring method! 24

  24. Syntactic sugar exhibit JP{ exhibit JP(){ ≡ }; }(); 25

  25. CJPs and JPIs Tight integration: A closure joinpoint is just a special joinpoint and is processed like any other joinpoint. 26

  26. Will it blend?

  27. Will it blend? www.willitblend.com

  28. t y Will it blend? p e ?

  29. Checked Exceptions jpi void JPNone(); jpi void JPEx() throws Exception; 30

  30. Checked Exceptions jpi void JPNone(); jpi void JPEx() throws Exception; Will it before JPNone() throws Exception { } type? before JPEx() throws Exception { } 30

  31. Checked Exceptions jpi void JPNone(); jpi void JPEx() throws Exception; Will it before JPNone() throws Exception { } type? before JPEx() throws Exception { } 30

  32. Checked Exceptions jpi void JPNone(); jpi void JPEx() throws Exception; before JPNone() throws Exception { } before JPEx() throws Exception { } void foo() { ... exhibit JPNone() { ... } Will it } type? void bar() { ... exhibit JPEx() { ... } } 30

  33. Checked Exceptions jpi void JPNone(); jpi void JPEx() throws Exception; before JPNone() throws Exception { } before JPEx() throws Exception { } void foo() { ... exhibit JPNone() { ... } Will it } type? void bar() { ... exhibit JPEx() { ... } } 30

  34. Invariant Return Types public aspect TestCase { static void correct() { HashSet s = exhibit JP { ... }; } jpi HashSet JP(); Set around JP() { return new TreeSet(); } } 31

  35. Invariant Return Types public aspect TestCase { static void correct() { HashSet s = exhibit JP { ... }; } jpi HashSet JP(); Set around JP() { return new TreeSet(); } } 31

  36. Invariant Return Types public aspect TestCase { static void correct() { HashSet s = exhibit JP { ... }; } jpi HashSet JP(); Set around JP() { return new TreeSet(); } } 31

  37. Invariant Return Types public aspect TestCase { static void correct() { HashSet s = exhibit JP { ... }; } jpi HashSet JP(); Set around JP() { HashSet around JP() { return new TreeSet(); } } 31

  38. Invariant Return Types public aspect TestCase { static void correct() { HashSet s = exhibit JP { ... }; } jpi HashSet JP(); Set around JP() { HashSet around JP() { return new TreeSet(); } } ... the same applies to argument types. (Alternative: StrongAspectJ, De Fraine et al., AOSD 08) 31

  39. Invariant Pointcuts jpi ¡void ¡JP(Number ¡n); aspect ¡A{ ¡ ¡exhibits ¡void ¡JP(Number ¡n) ¡: ¡call(void ¡*(..)) ¡&& ¡args(n); ¡ ¡public ¡static ¡void ¡main(String[] ¡args){ ¡ ¡ ¡ ¡ ¡ ¡foo(new ¡Integer(2)); ¡ ¡} ¡ ¡void ¡around ¡JP(Number ¡l){ ¡ ¡ ¡ ¡ ¡ ¡proceed(new ¡Float(3)); ¡ ¡} ¡ ¡public ¡static ¡void ¡foo(Integer ¡a){} } 32

  40. Invariant Pointcuts jpi ¡void ¡JP(Number ¡n); aspect ¡A{ ¡ ¡exhibits ¡void ¡JP(Number ¡n) ¡: ¡call(void ¡*(..)) ¡&& ¡args(n); ¡ ¡public ¡static ¡void ¡main(String[] ¡args){ ¡ ¡ ¡ ¡ ¡ ¡foo(new ¡Integer(2)); ¡ ¡} ¡ ¡void ¡around ¡JP(Number ¡l){ AspectJ: match ¡ ¡ ¡ ¡ ¡ ¡proceed(new ¡Float(3)); ¡ ¡} ¡ ¡public ¡static ¡void ¡foo(Integer ¡a){} } 32

  41. Invariant Pointcuts jpi ¡void ¡JP(Number ¡n); aspect ¡A{ ¡ ¡exhibits ¡void ¡JP(Number ¡n) ¡: ¡call(void ¡*(..)) ¡&& ¡args(n); argsinv(n); ¡ ¡public ¡static ¡void ¡main(String[] ¡args){ ¡ ¡ ¡ ¡ ¡ ¡foo(new ¡Integer(2)); ¡ ¡} ¡ ¡void ¡around ¡JP(Number ¡l){ argsinv: no match ¡ ¡ ¡ ¡ ¡ ¡proceed(new ¡Float(3)); ¡ ¡} ¡ ¡public ¡static ¡void ¡foo(Integer ¡a){} } 32

  42. Invariant Pointcuts Same for thisinv and targetinv Warning if exhibits uses this/target/args Not nice but maybe AspectJ should have used different semantics in the first place... 33

  43. More flexible typing through type parameters void printSet(Set s) { ... } Set around LogMe() { Set ret = proceed(); printSet(ret); jpi Set LogMe(); return ret; } exhibits Set LogMe(): call(* foo()); HashSet foo() { .. } HashSet s = foo(); 34

  44. More flexible typing through type parameters void printSet(Set s) { ... } Set around LogMe() { Set ret = proceed(); printSet(ret); jpi Set LogMe(); return ret; new TreeSet(); } exhibits Set LogMe(): call(* foo()); HashSet foo() { .. } HashSet s = foo(); 34

  45. More flexible typing through type parameters void printSet(Set s) { ... } Set around LogMe() { Set ret = proceed(); printSet(ret); jpi Set LogMe(); return ret; new TreeSet(); } exhibits Set LogMe(): call(* foo()); HashSet foo() { .. } HashSet s = foo(); 34

  46. More flexible typing through type parameters void printSet(Set s) { ... } Prevent error by Set around LogMe() { not matching! Set ret = proceed(); printSet(ret); jpi Set LogMe(); return ret; new TreeSet(); } exhibits Set LogMe(): call(* foo()); HashSet foo() { .. } HashSet s = foo(); 34

  47. More flexible typing through type parameters StrongAspectJ, De Fraine et al., AOSD 08 void printSet(Set s) { ... } <S extends Set> S around LogMe() { S ret = proceed(); printSet(ret); jpi <S extends Set> S LogMe(); return ret; } <S extends Set> exhibits S LogMe(): call(* foo()); HashSet foo() { .. } HashSet s = foo(); 35

  48. More flexible typing through type parameters StrongAspectJ, De Fraine et al., AOSD 08 void printSet(Set s) { ... } <S extends Set> S around LogMe() { S ret = proceed(); printSet(ret); jpi <S extends Set> S LogMe(); return ret; } <S extends Set> exhibits S LogMe(): call(* foo()); HashSet foo() { .. } HashSet s = foo(); 35

  49. More flexible typing through type parameters StrongAspectJ, De Fraine et al., AOSD 08 void printSet(Set s) { ... } <S extends Set> S around LogMe() { S ret = proceed(); printSet(ret); jpi <S extends Set> S LogMe(); return ret; new TreeSet(); } <S extends Set> exhibits S LogMe(): call(* foo()); HashSet foo() { .. } HashSet s = foo(); 35

  50. More flexible typing through type parameters StrongAspectJ, De Fraine et al., AOSD 08 void printSet(Set s) { ... } <S extends Set> S around LogMe() { S ret = proceed(); printSet(ret); return ret; } 35

  51. Supporting logging-like concerns through global pointcuts <R> R around LogMe() { long timeBef = time(); R ret = proceed(); print(timeBef-time()); return ret; } class A { <R> exhibits R LogMe(): ... } class B { <R> exhibits R LogMe(): ... } class C { <R> exhibits R LogMe(): ... } ... 36

  52. Supporting logging-like concerns through global pointcuts jpi <R> R LogMe(): call(* *(..)); Introduces default: class A { } ≡ class A { <R> exhibits R LogMe(): call(* *(..)); } 37

  53. Do allow for refinements... Seal a class: class A { <R> exhibits R LogMe(); } Add joinpoints: class A { <R> exhibits R LogMe(): global() || set(* *); } 38

  54. Do allow for refinements... Seal a class: class A { <R> exhibits R LogMe(); } Refine joinpoints: class A { <R> exhibits R LogMe(): global() && call(* foo()); } 39

  55. Result of typing rules Invocation of a closure can never fail at runtime! Strong typing! 40

  56. Result of typing rules Invocation of a closure can never fail at runtime! 40

  57. Join Point Polymorphism jpi ¡CheckingOut jpi ¡Buying jpi ¡Renting jpi ¡void ¡CheckingOut(float ¡price, ¡Customer ¡c) 41

  58. Join Point Polymorphism jpi ¡CheckingOut jpi ¡Buying jpi ¡Renting jpi ¡void ¡CheckingOut(float ¡price, ¡Customer ¡c) jpi ¡void ¡Buying(Item ¡i, ¡float ¡price, ¡Customer ¡cust) extends ¡CheckingOut(price,cust); 41

  59. Join Point Polymorphism jpi ¡CheckingOut jpi ¡Buying jpi ¡Renting jpi ¡void ¡CheckingOut(float ¡price, ¡Customer ¡c) jpi ¡void ¡Buying(Item ¡i, ¡float ¡price, ¡Customer ¡cust) extends ¡CheckingOut(price,cust); “width subtyping” 41

  60. Join Point Polymorphism jpi ¡CheckingOut jpi ¡Buying jpi ¡Renting jpi ¡void ¡CheckingOut(float ¡price, ¡Customer ¡c) jpi ¡void ¡Buying(Item ¡i, ¡float ¡price, ¡Customer ¡cust) extends ¡CheckingOut(price,cust); jpi ¡void ¡Renting(float ¡price, ¡int ¡amt, ¡Customer ¡c) extends ¡CheckingOut(price,c); 41

  61. Advice-dispatch semantics Aspect Discount around CheckingOut Buying around Buying Join Point The most specific jpi ¡CheckingOut advice gets executed. jpi ¡Buying jpi ¡Renting 42

Recommend


More recommend