Software Design and Development                   Winter 1997
COM 1205 
---------------------------------------------------------------------------

Assignment 3

Due date: Tuesday, Feb. 4 ---------------------------------------------------------------------------
This is a two week assignment.

This assignment is stored in file $SD/hw/3

in file assign.html

THEMES:

=========

On CCS Northeastern machines,

OO=/proj/adaptive/www/course/
AOO=/proj/adaptive/www/course/f96/

On the WWW, OO = http://www.ccs.neu.edu/research/demeter/course/
On the WWW, AOO = http://www.ccs.neu.edu/research/demeter/course/f96
The course directory is:

SD=$OO/w97-ug/

---------------------------------------------------------------------------

READING:

Read chapters 8, 11, 12 of the AP book.

The class dictionary for Demeter/Java in http://www.ccs.neu.edu/research/demeter/sources/DemeterJava/sourceC++/Java/demjava.cd

it defines the Demeter/Java notation.

Plus additional reading as described below.

--------------------------------------------------------------------------

PART 2 and PART 3 must be done in group mode. PART 1 and PART 4 and PART 5 must be done individually.

Organize your solution directory hw3 as follows: (files terminating in / are directories)

individual/
  README part1/ part4/ part5/
group/
  README part2/ part3/
Put additional files as needed.

To submit your individual homework, go to hw3/individual and call:

submit1205

This will automatically collect all the files (including files in subdirectories) and send them to com1205-grader.

Use the following header for your electronic homework submissions and put it at the top of the file README (for assignments which are done individually):

Course number: COM 1205 
Name:
Account name:
Assignment number:
Date:
Whenever you have questions about course material, please send e-mail to:

mail lieber johan ccs.courses.com1205@ccs.neu.edu

Set up your NU CCS account to use C++ compilers and the Demeter Tools/C++.

To get access to the latest version of the C++ compilers and the Demeter Tools/C++, copy the lines in the file $AOO/hw/3/.software which are not yet in your .software file into your file ~/.software and type command

resoft

More on the .software utility is in the man pages:

man software

==================================================================

It is time to build groups now. Each group should consist of no more than 3 students. This means that we will have about ten groups in the class. The group you select now will also do the project together.

For the assignments which are done in a group, use the following header at the top of file README:

Course number: COM 1205 
Names:
Account name of leader:
Assignment number:
Date:

The following applies to parts 2 and 3. We want to achieve good team work using a traversal/visitor style of programming. Therefore, you should design the interfaces of traversal functions, and visitors together and then split the work of implementing the traversals and visitors. Therefore, turn in the following

Team members: ....
abstract Visitor: 			responsible: team member 1
Visitor class SummingVisitor: 		responsible: team member 1
Visitor class PrintingVisitor: 		responsible: team member 2
Visitor class TreeStructureVisitor: 	responsible: team member 3
The traversal and class definitions code can also be split by class subsets:
              classes A, B, C, D, E, F, G, H, X
team member 1         .  .  .  
team member 2                  .  .  .
team member 3                           .  .  .
integration testing of traversal: team member 2

integration testing of complete program: team member 3

writing rest of program:

team member 1        countG() 
team member 2        print() 
team member 3        display() 
Of course, fill in the complete names of the team members.

The abstract Visitor and traversal code needs to be written very early since it is a prerequisite for testing the three concrete visitors.

It is important that each team member tests his or her code carefully before integration testing. This will require the writing of some additional code.

==================================================================

PART 1:

=======

Browse through the Demeter Tools/C++ User's Guide (in the Class Packet) to better understand the Laboratory Guide. Read and work through the Laboratory Guide and hand in all files modified. The Laboratory Guide is in the class package and online as described on page 589 of the AP book.

The purpose of this laboratory exercise is to see adaptive programming in operation in the C++ world. The principles are the same as in the Java world: we use structure-shy traversals and visitors. But the details are quite different as expressed at URLs

http://www.ccs.neu.edu/research/demeter/course/f96/APbookWithDemJava.html

http://www.ccs.neu.edu/research/demeter/course/f96/demjava/FromDemC++ToDemJava.html

Read both files before doing the Laboratory Guide.

PART 2:

=======

For this homework part you are encouraged to write a Java program from scratch. You should not use any tools except a Java compiler and interpreter (no Demeter tools) and of course, an editor and a machine which can run and compile Java.

Write a program for the class dictionary in: $SD/hw/3/visitor-by-hand/program.cd

The relevant classes are:

A = "a" <b1> B <c1> C [D] "enda".
B : E | F.
C = .
D = "d" .
E = "e".
F = <g1> G <h1> H <a1> A.
G =.
H = "h".
Write three methods in one program for this class dictionary but the three methods are allowed to use only one traversal function traverse(Visitor v) attached to all of the above classes.

The three tasks to be done by the three methods are:

Test your functions on three different A-objects using code like:
in class Main:
 static public void main(String args[]) throws Exception {
   A a = ... // write constructor calls to build an A-object. See:
   // /proj/adaptive/www/sources/DemeterJava/examples/j-c-bypassing/program.beh
   // for an example.

   System.out.println("print:");
   a.g_print(); 
   System.out.println();
   System.out.println("tree structure:");
   a.display();
   System.out.println("count:");
   int result = a.countG();
   System.out.println(result + " done ");  
}

   print() should be implemented by a call traverse(p)
   where p is a PrintingVisitor-object.

   display() should be implemented by a call traverse(t)
   where t is a TreeStructureVisitor-object.
 
   countG() should be implemented by a call traverse(s)
   where s is a SummingVisitor-object.
To achieve what you want, you need to introduce an abstract Visitor class, as described in class and in the Design Pattern book. See also the example about manual visitor/traversal style programming and the context object paper (journal version) for an extended discussion.

You need an abstract class:

Visitor : PrintingVisitor | TreeStructureVisitor | SummingVisitor.
For the abstract Visitor class you define empty before and after methods which have a host argument. In the subclasses you override the methods where the behavior needs to be non-empty.

Your traversal functions will call the before and after methods of the visitor. First the before method is called, then the traversal is done and then the after method is called.

Turn in your complete Java-program and the output produced for your three test cases.

PART 3:

=======

Repeat PART 2 for the class dictionary in: $SD/hw/3/visitor-by-hand2/program.cd

The relevant classes of the cd are:

A = "a" X C [D].
X = B.
B : E | F.
C = .
D = "d" .
E = "e".
F = G H.
G =.
H = "h".
Notice that the class dictionary is only slightly different from the one in PART 2. You have to figure out what each team member needs to update in the code assigned to him/her. The figuring out what needs to be updated should be done as a group but the implementation is completed by each team member.

PART 4:

=======

Now the restriction of using Demeter/Java is lifted. You can now take advantage of the brain power which CCS students and faculty have put into Demeter/Java. We hope you will be pleased by how the task is now simplified so that you can do it easily yourself in 30 minutes.

Do PART 2 and PART 3 using Demeter/Java. Copy the directories:

$SD/hw/3/visitor-by-hand/* and $SD/hw/3/visitor-by-hand2/*

and modify the program.cd and program.beh and program.input files as needed.

To regenerate:

make test

Note that sometimes it is necessary to use "make clean" before "make test".

Make sure you add the visitor classes to the class dictionary.

Please hand in only a short description of the modifications you did to program.cd and program.beh. Write a paragraph which describes the difference in the amount of work you did in PART 2 and 3 and compare it with the amount of work you did in PART 4.

PART 5: (to be done individually)

=======

To be good at object-oriented software development, you need to have several skills, including:

In this part you focus on defining the structure of your objects, i.e., on how to write class dictionaries.

We first start with simple class dictionaries. Therefore, first do the work described in 17.5.1 and 17.5.2 and 17.5.3 on pages 551 and 552 of the AP-book. Instead of using Demeter/C++, use Demeter/Java to test your sentences. Turn in your class dictionaries and your sentences and for each class dictionary a statement (comment) which says: My class dictionary was accepted by j-sem-check without warning or error. j-sem-check is explained below.

See http://www.ccs.neu.edu/research/demeter/sources/DemeterJava/examples/how-to-use-Demeter-with-Java on how to use Demeter/Java.

When writing your class dictionaries, follow the Terminal-Buffer rule described on page 393 of the AP book.

Also follow the following Repetition-Buffer rule: A repetition class should be used as the only part class of a construction class. Example:

Body                    = "{" [Initialize] PathDirective Wrappers "}".
Wrappers                = [ < wrappers> Wrapper_SList ] .       
Wrapper_SList 		~ Wrapper {  Wrapper } .
Here Wrappers is the buffer class for the wrapper list. The reason for buffering repetition classes is that their names might change later. If we need to pass around wrappers, it is better to pass around Wrappers-objects than Wrapper_SList-object since Wrapper_SList might be renamed to Wrapper_CVector later.

When writing your class dictionaries, it can be confusing where you should put the syntax in a construction class definition. You could write class definitions like:

A = "a" "b" B "c" C "d" D "enda".
B = .
C = .
D = .
But it is better to use the following style which uses syntax only at the beginning and end of a construction class definition.
A = "a" B C D "enda".
B = "b".
C = "c".
D = "d".
Therefore, follow the Prefix-Suffix-Grammar rule: A construction class definition in a class dictionary may contain syntax only as a prefix or suffix of the class definition. Between the parts no syntax is allowed. To make your job of developing class dictionaries easier, I have developed a little script called j-sem-check for testing your Demeter/Java class dictionaries. This tool gives you much better error messages than the current Demeter/Java system using Jack. j-sem-check will also help you to make your language readable with a look-ahead of one symbol.

Now after you have gained experience in designing small class dictionaries, we go for a larger one. This class dictionary is about what you learn in the AP-book: propagation patterns.

Object-oriented programming has three key ingredients: class dictionaries, traversals and visitors. But sometimes, those ingredients require us to write long programs and therefore, we look for abbreviations, also called syntactic sugar. Propagation patterns are such a mechanism to make it easier to program with traversals and visitors.

Consider the task of computing the total of all salaries paid by a company. We need to define a method called sum_salaries for class Company. To implement the method we need to define a visitor class called SummingVisitor. We also need to define a traversal method "allSalaries". The body of method sum_salaries will instantiate the Visitor and call the method allSalaries with the summingVisitor-object as argument. For a related example, see http://www.ccs.neu.edu/research/demeter/sources/DemeterJava/examples/j-c-holding/ in file holding.beh.

This all can be said with a propagation pattern:

Company {
  traversal-pp int sum_salaries() {
    initialize (@ 0 @)  // initialize return_val to 0
    to Salary		// traversal
    before Salary (@ return_val = return_val + host.get(v).intValue(): @)
  }
}
Propagation patterns have not been implemented in Demeter/Java and the purpose of this part is to design a part of the class dictionary for this extended Demeter/Java.

Extend the class dictionary below so that it can handle the following input:

Company {
  traversal-pp int sum_salaries() {
    initialize (@ 0 @)  // initialize return_val to 0
    to Salary		// traversal
    before Salary (@ return_val = return_val + host.get(v).intValue(): @)
  }
}

Shape {
  traversal-pp Integer gp1x(){
    bypassing {-> *,p2,*, -> *,y,*} to Integer
    before Integer (@ return_val = this; @) 
  }
}

ClassGraph {
  traversal-pp void constrClassNames() {
      through :cdef ClassDef  to Construct
      // the class definition is made available in variable cdef
      before Construct
        (@ System.out.println(cdef.getClassName()); @)
  }
}

X {
  traversal-pp int f(float f, int i, A a) {
    initialize (@ 0 @)
    bypassing {X,Y, -> *,r,R} 
    through {:x X, :y Y, -> *,r,:rv R} 
     // the wrappers below may refer to x,y and rv
     to Z
    before {R,S} (@ ... @)
    after {U,V} (@ ... @)
  }
}
The class dictionary:
// -- class dictionary for Demeter/Java with propagation patterns

//////////////////////
// Behavior (methods).
//////////////////////
// man g_print (Demeter/C++) explains the pretty printing commands
// *l *s + -

ProgramBehavior		= [ <behavior> DList(ClassBehavior) ] .

ClassBehavior		= ClassName ClassMethods.

ClassMethods		= "{" *l + [ <methods> SList(Method) ] - "}" .

Method			: Traversal | TraversalPP| Behavior.
Behavior		: Wrapper | Verbatim.


// Class graph traversal specifications.
Traversal		= "traversal" TraversalName TraversalArgs "{" *l
			+ PathDirective ";" - *l
			"}".
TraversalPP		= "traversal-pp" 
			  <returnType> UNKNOWN1
			  UNKNOWN2
			  UNKNOWN3
			  UNKNOWN4.
Args			= "(" [ <l> Commalist(UNKNOWN5) ] ")".
Arg			= <typ> JavaTypeName  <arg> Variable. 
Body			= "{" [UNKNOWN6] UNKNOWN7 UNKNOWN8 "}".
Initialize		= "initialize" UNKNOWN9.

Wrappers		= *l + [ <wrappers> SList(UNKNOWN10) ] -  .

TraversalArgs		= "(" [ <visitors> Commalist(Visitor) ] ")" .

Visitor			= ClassName VisitorName.

PathDirective		= [ BypassingDirective ]
			  [ ThroughDirective ]
			  TargetDirective.

BypassingDirective	= "bypassing" <glob> GlobSpec.
ThroughDirective	= "through" <glob> GlobSpec.

TargetDirective		: To | ToStop *common* <targets> ClassGlobSpec.
To			= "to".
ToStop			= "to-stop".

GlobSpec		: OneGlob | GlobSet.
OneGlob			= Glob.
GlobSet			= "{" [ <globs> Commalist(Glob) ] "}".

Glob			: ClassGlob | EdgeGlob.
EdgeGlob		: PartGlob | SubclassGlob | SuperclassGlob.

ClassGlob		= <dest> ClassNameGlob.
PartGlob		= "->" <source> ClassNameGlob ","
			       <edge> PartNameGlob "," <dest> ClassNameGlob.
SubclassGlob		= "=>" <source> ClassNameGlob "," <dest> ClassNameGlob.
SuperclassGlob		= ":>" <source> ClassNameGlob "," <dest> ClassNameGlob.

ClassNameGlob		: ClassNameExact | AnyClass.
ClassNameExact		= [UNKNOWN11 Variable] ClassName.
AnyClass		= "*".

PartNameGlob		: PartNameExact | AnyPart.
PartNameExact		= PartName.
AnyPart			= "*".

ClassGlobSpec		: OneClassGlob | ClassGlobSet.
OneClassGlob		= ClassGlob.
ClassGlobSet		= "{" <classglobs> Commalist(ClassGlob) "}".


// Before and after wrappers.
Wrapper			: Before | After *common* <hosts> HostSpec JavaCode.

Before			= "before".
After			= "after".

HostSpec		: ClassGlobSpec.


// Verbatim java code.
Verbatim		= JavaCode.


// Terminal buffer classes.
DirName			= <name> Ident.
ClassName		= <name> Ident.
PartName		= <name> Ident.
TraversalName		= <name> Ident.
VisitorName		= <name> Ident.
MethodName		= <name> Ident.
JavaCode		= <code> Text.

JavaTypeName		= <name> Ident.
Variable		= <name> Ident.

// Parameterized class definitions.
List(S) ~ {S}.
SList(S) ~ S { *l S } *l .
DList(S) ~ S { *l *l S } *l .
Commalist(S) ~ S {"," S}.
Barlist(S) ~ S { *l "|" S}.

Main = .
Turn in the UNKNOWNs.

Discussion

Notice that it is not too hard to translate a propagation pattern back into traversal/visitor style. All the wrappers become the methods in a new visitor class called V. V is defined by:
V = <return_val> WhatEverType.
If the propagation pattern has arguments, we need an additional visitor class called ArgV which has as many parts as the propagation pattern has arguments. The initalization code is used to initialize return_val.

For example, the propagation pattern:

Company {
  traversal-pp int sum_salaries() {
    initialize (@ 0 @)  // initialize return_val to 0
    to Salary		// traversal
    before Salary (@ return_val = return_val + host.get(v).intValue(); @)
  }
}
is translated into
Company {
  (@
    int sum_salaries() {
      SummingVisitor sv = new SummingVisitor( 0 );
      this.allSalaries(sv);
      return sv.get_return_val();
  @)
  traversal allSalaries(SummingVisitor sv) {
    to Salary; }
}
 
SummingVisitor {
  before Salary (@ return_val = return_val + host.get(v).intValue(); @)
}
As this example shows, propagation patterns are an abbreviated form for certain kinds of adaptive programs. But propagation patterns don't take advantage of the full power of visitors: They use only very simple visitors.

=====================================================================

Corrections to the Laboratory Guide:

The page numbers below refer to the TOP page numbers in the CLASS packet (NOT the bigger number on the bottom).

>From a happy user:

Hi Crista:
 
I just finished working through the Demeter Lab Guide and already feel
a lot more comfortable with Demeter. The Lab Guide is concise, clear
and written with a great deal of empathy for the user. Congratulations
for doing such an excellent job with the Lab Guide!
 
Here are some minor nits:
 
1. On page 36 "./run library-init" should be "./run library-input".


2. On page 37 
     D = "d-object" . .
   It should be
     D = "d-object" .


3. There are a number of places where memory allocation is done but there
   is no corresponding free. Since this is just a demo it is obviously not
   important. Most of these can be fixed easily.

E-mail submission

Please follow the following rules:

HOW

Prepare your submission directory with all the relevant information (including file README) and type

submit1205

in your directory.

For group submission use the same procedure, but please only one message per group.

COMPLETE SOLUTION

Send the complete text of your homework solution with one call to submit1205. Don't just send a message "my solution is in directory ...". The solution with the submit1205 command keeps your solution protected from access by others and allows for faster grading.

COMPUTER USAGE:

For doing the assignments you will need to use the Demeter Tools/C++. You can do that by Regarding 1 and 3, see URL: http://www.ccs.neu.edu/labs/index.html

Options 1 and 3 require no installation on your part but access will be a bit slow depending on your location.

Option 2 will be faster but you need to install Demeter. You do not however need root access for that .. Just plenty of disk space.. :) This installation process will become much simpler after Demeter is implemented in Java running also under Windows.

===========================

Honors adjunct class:

PART 6: (To be done individually)

=======

Implemement a tool which checks for the Terminal-Buffer rule, page 393 of the AP book. Use the class dictionary in $SD/hw/1/graph/class-graph.cd

The following class definition should be rejected:

A = <x> Integer <y> Integer.
The following two are legal:
A = <x> Coord <y> Coord.
Coord = <l> Integer.
You may write the design ruler checker directly in Java or use the Demeter/Java tools. But in any case, the design you express in Demeter/Java notation.

Treat any undefined class (i.e. one that does not appear on the left side of a class definition) as a terminal class. This includes, for example:

The Java wrapper classes (in package java.lang): Boolean Character Double Float Integer Long

The Java classes (in package java.lang): String StringBuffer

The classes (in package edu.neu.ccs.demeter currently only called demeter): Ident Text

Turn in your complete Java program and *.cd and *.beh files.