@TECHREPORT{po-vis:ahmed-karl,
AUTHOR = "Ahmed Abdelmeged and Karl Lieberherr",
TITLE = "{Recursive Adaptive Computations Using Interposition Visitors}",
YEAR = "2007",
INSTITUTION = "Northeastern University, Boston",
MONTH = "May",
NUMBER =  "NU-CCIS-07-06,
NOTE = "OOPSLA 2007 Poster"
}

Paper.

Implementation.

Notes by Karl:

Name change: PerObject has been changed to Interposition. A better name motivated by the ECOOP 2007 paper by Balzer/Gross/Eugster.

This is a modularized version of the code in the TR. We start with the tangled code from the paper and then modularize it using inheritance. Instead of using inheritance we plan to use a DSL for PO visitor composition.

public class CheckerVisitor extends Visitor {
  int totalViolations = 0; 
  @PerObject {
     className = "Container"; initializer = "0"
  } int myWeight;
  public void before(Element e){
           myWeight += e.weight;}
  public void after(Container c){
           myWeight += c.myWeight;
           boolean vio = 
             c.capacity < c.myWeight;
           if(vio){ totalViolations++; }
        }
}
 
Concerns:

weight summation
  WeightVisitor
violation predicate
  VioVisitor
conditional update
  Updater 
    CounterAcc 
    ListAcc

public class WeightVisitor extends Visitor {
  int totalViolations = 0; 
  @PerObject {
     className = "Container"; initializer = "0"
  } int myWeight;
  public void before(Element e){
           myWeight += e.weight;}
  public void after(Container c){
           myWeight += c.myWeight; }
}
 

public class VioVisitor extends WeightVisitor {
  @PerObject {
    className = "Container"
  } boolean vio;
  public void after(Container c){
           super.after(c);
           c.vio = c.capacity < c.myWeight;
        }
}

public class Updater extends VioVisitor {
    public void after(Container c){
           super.after(c);
           if(c.vio){ update(c); }
        }
    void update(Container c) {};
}

public class CounterAcc 
    extends Updater {
  int totalViolations = 0; 
  void update(Container c) {
           totalViolations++; }
}

public class ListAcc extends Updater {
  List violations = new List(); 
  void update(Container c) {
     violations = new Cons(c,violations); }
}

The current TR might give the wrong impression that PO visitors are only useful for recursive computations. They are also useful on non-recursive structures whenever we need easy access to objects "higher" up in the object. They are a simplified version of transportation patterns described in chapter 10 of my book.

BUT, as pointed out by Bryan Chadwick, PO visitors for non-recursive structures can be eliminated. For example, in the Shannon Decomposition (CNF reduction) example below, newLiterals and newClauses can be made visitor instance variables, newLiterals can be reinitalized before each Clause and newClauses can be initialized before Formula. A similar argument for sats and unsats. Consider the interposition visitor version of the CNF formula reduction problem:

Formula = clauses: List(Clause) 
  perobject sats: int 
  perobject unsats: int
  perobject newClauses: List(Clause).
Clause = literals: List(Literal) 
  perobject newLiterals: List(Literal).
Literal : Pos | Neg common Variable.
Pos = . Neg = .
Variable = v: int.


void after (Literal l2) { reduce(l1,l2);}
  reduce(l1, l2)
  reduce(Pos(v), Pos(v)) = true: sats++
  reduce(Neg(v), Neg(v)) = true: sats++
  reduce(Neg(v), Pos(v)) = false: skip l2
  reduce(Pos(v), Neg(v)) = false: skip l2
  reduce(l1, l2) = l2 if l1 and l2 do not refer to the same variable: 
    add l2 to newLiterals

void after (Clause clause)
  if newLiterals is empty: unsats++ else add clause to newClauses;

Visitors influence traversals. Aspects influence Java programs. PO (perobject) variables are a part of visitors. Does it make sense to have perobject variables for aspects?

PO variables for aspects are also attached to a class. They are visible in the entire cflow of a suitable pointcut. Has this been proposed on the AspectJ mailing list?

There are several opportunities for optimization based on an analysis of how the visitors use the the per-object variable.

One of the benefits of attribute grammars is that they can transport information from anywhere in the abstract syntax tree to anywhere else, in a controlled and formal way. PO visitors share the same property but they not only transport, they also update the information automatically as part of a traversal.

A useful equation: Attribute Grammar = Parsing + AP + a universal traversal + simple PO visitors. The simple visitors update the inherited and synthesized attributes.