Question 1: =========== In the following you are given two class dictionaries CD1 and CD2 and corresponding traversal code T1 and T2. The traversal code T1 is for CD1 and the traversal code T2 is for CD2. The claim is that the traversal code comes from _one_ traversal function which is expressed with a traversal directive. Find a _smallest such directive. Find the UNKNOWN in the following: A{ traversal t(V v){ bypassing ->*,l,* to B;} // in /proj/asl/lieber/java/java-envs/jk-common CD1: ======================================== A = K Q. K = L. L = B. Q = B. B = . V = . Main = . T1 ========================================= class A { // omitted public void t_traverse ( V v ) { q.t_traverse(v); } } class Q { // omitted public void t_traverse ( V v ) { b.t_traverse(v); } } class B { // omitted public void t_traverse ( V v ) { v.before(this); } } // in /proj/asl/lieber/java/java-envs/jk-common2 CD2: ========================================== A = K. K : R | S *common* P "sep" Q. P = B. Q = B. R = "r". S = "s". B = ["c" C]. C = L. L = A. V = . Main = . T2: =========================================== class A { // omitted public void t_traverse ( V v ) { k.t_traverse(v); } } abstract class K { // omitted public void t_traverse ( V v ) { p.t_traverse(v); q.t_traverse(v); } } class P { // omitted public void t_traverse ( V v ) { b.t_traverse(v); } } class Q { // omitted public void t_traverse ( V v ) { b.t_traverse(v); } } class R extends K { // omitted public void t_traverse ( V v ) { super.t_traverse (v); } } class S extends K { // omitted public void t_traverse ( V v ) { super.t_traverse (v); } } class B { // omitted public void t_traverse ( V v ) { v.before(this); } } Question 2: =========== Variation of the Law of Demeter for Adaptive Programming Consider the following Law of Demeter for visitors: In a visitor method M (a before or after method) attached to visitor class V, only use methods of class V, of the host class and of classes which are instantiated in M. (Specifically, it is disallowed to use methods of the classes of immediate parts of host and this.) Answer the following questions: 1. Is this version of the Law of Demeter too restrictive? Assume M contains the code fragment: host.get_x().f(); How could you rewrite the code so that it follows the Law of Demeter for visitors? 2. Assume M contains the code fragment: this.get_x().f(); How could you rewrite the code so that it follows the Law of Demeter for visitors? 3. Allow also to use methods of the classes of the immediate parts of V. This means that this.get_x().f() is now allowed. Is this a better version of the Law of Demeter for visitors? Discuss the pros and cons. Question 3: // /proj/asl/lieber/java/java-envs/e/jk-detection2/cpp Consider the following class dictionary, object and corresponding sentence. Find the UNKNOWNs. Class dictionary: Start = List(A). List(S) ~ S {"," S}. A = ["b" B] ["c" C]. B : D *common* X. C = ["d" D] ["e" E]. D : F *common* Y. E = ["f" F]. F : U *common* Z. U = . X = . Y = . Z = . Main = . V = C_RestrCountVisitor E_RestrCountVisitor. C_RestrCountVisitor = Integer C_DetectionVisitor. E_RestrCountVisitor = Integer E_DetectionVisitor. C_DetectionVisitor = C. E_DetectionVisitor = E. Object: : Start ( < a_list > : A_List { : A ( < b > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) ) , : A ( < b > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) < c > : C ( ) ) , : A ( < b > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) < c > : C ( < d > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) ) ) , : A ( < b > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) < c > : C ( < d > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) < e > : E ( < f > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) ) ) ) } ) Sentence: b , b c , b c d , b c d e f Question 4: =========== Consider the following class dictionary program.cd and behavior file program.beh. The behavior file has the task of printing two numbers for a given Start-object: the number of all Z-objects containing a C-object and the number of all Z-objects containing a E-object. Both numbers are computed in one traversal. For example, on input c e f, c d the output is: java Main < program.input 2 Z-objects with C-objects 1 Z-objects with E-objects done: =========================== Find the UNKNOWNs below: Class dictionary program.cd =========================== Start = List(A). List(S) ~ S {"," S}. A = ["b" B] ["c" C]. B : D *common* X. C = ["d" D] ["e" E]. D : F *common* Y. E = ["f" F]. F : U *common* Z. U = . X = . Y = . Z = . Main = . V = C_RestrCountVisitor E_RestrCountVisitor. C_RestrCountVisitor = Integer C_DetectionVisitor. E_RestrCountVisitor = Integer E_DetectionVisitor. C_DetectionVisitor = C. E_DetectionVisitor = E. Behavior file program.beh ========================= Start{ traversal t( C_DetectionVisitor cd, E_DetectionVisitor ed, C_RestrCountVisitor cr, E_RestrCountVisitor er, V v){ to Z;} (@ void f() { C_DetectionVisitor cd = new C_DetectionVisitor(); E_DetectionVisitor ed = new E_DetectionVisitor(); C_RestrCountVisitor cr = new C_RestrCountVisitor(new Integer(0),cd); E_RestrCountVisitor er = new E_RestrCountVisitor(new Integer(0),ed); V v = new V(cr,er); this.t(cd,ed,cr,er,v); } @) } V{ after Start (@ System.out.println(rc.get_c().intValue() + " Z-objects with C-objects"); System.out.println(re.get_c().intValue() + " Z-objects with E-objects"); @) } C_DetectionVisitor { before C (@ d = host; @) after C (@ d = null; @) } E_DetectionVisitor { before E (@ d = host; @) after E (@ d = null; @) } C_RestrCountVisitor { before Z (@ if (d.get_d() != null) c = new Integer(c.intValue() + 1); @) } E_RestrCountVisitor { before Z (@ if (d.get_d() != null) c = new Integer(c.intValue() + 1); @) } Main { (@ static public void main(String args[]) throws Exception { Start a = Start.parse(System.in); a.f(); System.out.println("done: "); } @) } Question 5: =========== Consider the following behavior file program.beh. Find a class dictionary program.cd so that program.beh and program.cd together define a Java program which compiles. Find the UNKNOWNs below: Program { (@ /** Prints all construction class names in a given class graph. A program to show second order visitors. Requires a visitor to traverse a visitor. Also counts the total number of construction classes. */ public static void main(String args[]) throws Exception { Program p = parse(System.in); p.print_and_count_cons_classes(); } @) (@ public void print_and_count_cons_classes() { ClassNameTranspVisitor cntv = new ClassNameTranspVisitor(); PrintConsClassesVisitor pcv = new PrintConsClassesVisitor(cntv); CountingVisitor cv = new CountingVisitor( new Integer(0)); this.toAllConstructionClasses(pcv,cntv,cv); } @) traversal toAllConstructionClasses( PrintConsClassesVisitor pcv, ClassNameTranspVisitor cntv, CountingVisitor cv ) { to ConstructionClass; } } CountingVisitor { before ConstructionClass (@ this.set_total(new Integer(total.intValue() + 1)); @) after Program (@ System.out.println(this.get_total().intValue() + " = number of construction classes"); @) } ClassNameTranspVisitor { before ClassDef (@ this.set_pcn(host.get_classname()); @)} ClassNameRetVisitor { before ClassName (@ this.set_cn(host); @)} PrintConsClassesVisitor { traversal toClassName( ClassNameRetVisitor cnrv) { bypassing -> *,parameters,* to ClassName;} (@ /** Retrieve the class name from the visitor. Requires a traversal from the visitor class which itself needs a visitor. */ public ClassName dig_out() { ClassNameRetVisitor cnrv = new ClassNameRetVisitor(); this.toClassName(cnrv); return cnrv.get_cn(); } @) before ConstructionClass (@ System.out.println("construction class " + this.dig_out().get_name()) ; @) } // demjava.cd -- class dictionary for Demeter/Java Program = ClassDef. ClassDef = ClassName ConstructionClass ".". ConstructionClass = "=". // Terminal buffer classes. ClassName = Ident. // Visitors. CountingVisitor = Integer. ClassNameRetVisitor = ClassName. ClassNameTranspVisitor = ClassName. PrintConsClassesVisitor = ClassNameTranspVisitor.