You are on page 1of 3

Reflections

3/3/18 Ann Tung 913019827



Fixed tree with known types of nodes to minimize coupling of processor objects (printing,
decorating) to tree objects (AST accept walking)

Each visitor defines procedures to for every type of node visitation: visitProgramTree,
visitBlockTree, etc.

Example:
PrintVisitor visitor = new PrintVisitor();
tree.accept( visitor);
return visitor.visitProgramTree( this ) // in tree object class method definition
visitProgramTree: print( “Program”, tree ); // display line of the node
visitKids( tree ); // tells each child node to accept the visitor

<<interface>>
Element
^ ^
| |
ElementOne ElementTwo
+accept(v: Visitor ) +accept(v: Visitor)


<<interface>>
Visitor
+visit(e: ElementOne)
^
|
ConcreteVisitor
+visit(e: ElementOne)

<<interface>>
Visitor
+visit(e: ElementTwo)
^
|
ConcreteVisitor
+visit(e: ElementTwo)

Apparent type: AST tree (variable and method declarations; super type where calls are legal)
Actual type: RelOpTree (AST tree = new RelOpTree();)
Ex: getSymbol method in the RelOpTree class not in AST class:
AST t = new RelOpTree();
t.getSymbol(); // “cannot find symbol” since the apparent class of t doesn’t contain getSymbol
Dynamic Binding (Dynamic Dispatch: mapping a message to method) calls to objects’s actual
type at run time through a dispatch vector which references to methods of implementation.
AST t = new RelOpTree();
t.accept( pv ); // the accept method in the actual class RelOpTree will be called.

Double Dispatch mechanism (instead of switch statements): call corresponding visitor accept
method which then calls the corresponding visitor method, adding polymorphism capability

Switch statements coupled with cases can be omitted in adding all new cases

Single dispatch: an implementation is decided at runtime based on the single run type of the
this object

Double dispatch: dynamically select method based on run-time type of receiver (single
dispatch) and run-time type of argument, applying dynamic binding twice.

AST tree;
PrintVisitor visitor = new PrintVisitor();
Tree.accept( visitor ); // the tree supposely references a ProgramTree object at the parser
( ProgramTree.accept( visitor ) // ProgramTree is passed along with the this argument );
visitor.visitProgramTree( this );
// dynamic dispatch determines at RUNTIME the programTree’s visitProgramTree to execute






















Assignment 3: needs to update Compiler to implement a different visitor: OffsetVisitor and
DrawOffsetVisitor.


OffsetVisitor.java: post order traversal. create hash table AST->Offset to record x offset, depth.

Setup: create an array to track the next available offset at each level. Assume max depth 100. If
a node has no children, assign the node’s offset to the next available offset of its level. Update
the next available offset (adding 2).

Hash table:
Key (node) Offset (left, depth)
ProgramTree ptOffset
etc etc

Calculate parent node’s offset after visiting all its children:
Offset = (rightmost child’s offset + leftmost child’s offset) / 2

If offset < next available offset at its level: recursively shift all child’s offsets by
( next available offset for this node’s level – offset )

Update the next available offset at each level while children are updated.

Offset is set to be max ( Offset, next available offset of its level ).

Update net available offset of its level.


DrawOffsetVisitor ( With result passed from OfficeVisitor. Unit measure in pixel)

Setup: Size of canvas : node width x (1+max offset)
by
node height x (1+max depth)

Canvas:
Width = 16 * NODE_WIDTH + ( (16-1) * NODE_ROW_DISTANCE )
Height = same-ish

calculate the position of each node from node width, node height, padding between nodes.

Calculate its (mid-point, bottom edge) and draw a line from there to each child’s (mid-point,
top edge). Mid-point = (left) + 1/2 (Node width).

You might also like