001    // Solutions to various exercises in the paper
002    
003    import java.util.*;
004    aspect Exercises {
005      // Exercise 8: alreadyDeclared
006        syn boolean State.alreadyDeclared() = lookup(this.getLabel()) != this;
007      
008      // Exercise 9: multiplyDeclared
009      syn boolean State.multiplyDeclared() =
010          alreadyDeclared() || hasLaterNamesake();
011      
012      syn boolean State.hasLaterNamesake() =
013          lookupForward(getLabel()) != null;
014      
015      inh State Declaration.lookupForward(String label);
016        
017      eq StateMachine.getDeclaration(int i).lookupForward(String label) {
018        for (int k = i+1; k<getNumDeclaration(); k++) {
019          Declaration d = getDeclaration(k);
020          State match = d.localLookup(label);
021          if (match != null) return match;
022        }
023        return null;
024      }
025    
026      // Exercise 10: altTransitions
027      syn Set<Transition> State.altTransitions() = transitionsOf(this);
028      inh Set<Transition> State.transitionsOf(State s);
029      
030      eq StateMachine.getDeclaration(int i).transitionsOf(State s) {
031        HashSet<Transition> result = new HashSet<Transition>();
032        for (Declaration d : getDeclarationList()) {
033          Transition t = d.transitionOf(s);
034          if (t != null) result.add(t);
035        }
036        return result;
037      }
038      
039      syn Transition Declaration.transitionOf(State s) = null;
040      eq Transition.transitionOf(State s) {
041        if (source() == s)
042          return this;
043        else
044          return null;
045      }
046    
047      // Exercise 11: altSuccessors
048      coll Set<State> State.altSuccessors() [new HashSet<State>()] with add;
049      
050      Transition contributes target()
051        when target() != null && source() != null
052        to State.altSuccessors()
053        for source();
054      
055    
056      // Exercise 12: predecessors
057      coll Set<State> State.predecessors() [new HashSet<State>()] with add;
058      
059      State contributes this
060        to State.predecessors()
061        for each successors();
062    
063      // Exercise 13: numberOfTransitions
064      syn int StateMachine.numberOfTransitions() =
065          numberOfTransitionsColl().value();
066      coll Counter StateMachine.numberOfTransitionsColl() [new Counter()] with add;
067      
068      Transition contributes 1
069        to StateMachine.numberOfTransitionsColl()
070        for theMachine();
071        
072      inh StateMachine Declaration.theMachine();
073      eq  StateMachine.getDeclaration(int i).theMachine() = this;
074     
075      public class Counter {
076        private int value;
077        public Counter() { value = 0; }
078        public void add(int value) { this.value += value; }
079        public int value() { return value; }
080      }
081    
082      // Exercise 14: errors
083      coll Set<String> StateMachine.errors()
084           [new HashSet<String>()] with add;
085    
086      State contributes getLabel()+" is already declared"
087      when alreadyDeclared()
088      to StateMachine.errors()
089      for theMachine();
090      
091      Transition contributes "Missing declaration of "+getSourceLabel()
092      when source() == null
093      to StateMachine.errors()
094      for theMachine();
095      
096      Transition contributes "Missing declaration of "+getTargetLabel()
097      when target() == null
098      to StateMachine.errors()
099      for theMachine();
100    
101      // Exercise 18: altReachable
102      coll Set<State> State.altReachable() circular [new HashSet<State>()] with addAll;
103      
104      State contributes union(asSet(this),altReachable())
105        to State.altReachable()
106        for each predecessors();
107        
108      // helper functions asSet and union
109      Set<State> ASTNode.asSet(State o) {
110        HashSet<State> result = new HashSet<State>();
111        result.add(o);
112        return result;
113      }
114      
115      Set<State> ASTNode.union(Set<State> s1, Set<State> s2) {
116        HashSet<State> result = new HashSet<State>();
117        for (State s: s1) result.add(s);
118        for (State s: s2) result.add(s);
119        return result;
120      }
121    }