Notes
Outline
Introduction
Introduction
Design criteria
Code reuse
Based on the Java parser of Ptolemy II (well, sort of…)
Reduce effort to develop back-end modules
APIs to inspect the ASTs
A generic traversal mechanism: Visitor design pattern
An annotation mechanism: Properties
Support incremental compilation (to be implemented)
Transparent from the point of view of the user
Reuse ASTs from previous compilations
Generate “skeletons” Meta-model files
The implementation
Language: Java (1.2 or later)
Development:  Unix
Sources (CVS): metro/src/
Packages:
  metropolis/metamodel     Main package of the compiler
  metropolis/metamodel/frontend   Front-end of the compiler
  metropolis/metamodel/nodetypes   Definiton of the nodes of the AST
  metropolis/metamodel/backends   Back-end modules of the compiler
Overall compilation flow
The frontend
The frontend
Abstract syntax trees
An abstract syntax tree (AST) represents how a program has been derived from the grammar.
The nodes of the AST represent productions of the grammar
The leaves of the AST represent the terminal symbols
Abstract syntax trees
Nodes of the ASTs are defined in a class hierarchy
Nodes provide a constructor that defines all children and fields:
a child
a single node
a list of nodes
a terminal symbol
identifier
set of modifiers
constants
Annotations store semantic information.
Slide 10
Slide 11
Abstract syntax trees
Each node of the AST has the following attributes:
a list with a fixed number of children
a list of annotations
a list of visitors that have visited the node
an identifier of this class of nodes
The basic operations that can be performed on a node:
Retrieve the parent getParent()
Retrieve a child getChild(index)
Replace a child setChild(index, val)
Set/get methods for each child getName(), setName(val)
Get the unique ID of the class classID()
Get a copy of a subtree clone()
Traversal of the AST accept(visitor,args)
Annotate the node setProperty(index, val)
Read an annotation getProperty(index)
Abstract syntax trees
Example: annotate the AST of a file with the number of classes   declared in that file.
Annotations
The front-end provides several annotations with semantic information
On the CompileUnitNode: information about the file
On other nodes: specific informations
Declarations
Each node that declares a new name is annotated with a unique object, the declaration.
Each reference to a name is annotated with the unique declaration of that name.
Declarations: APIs
Basic information:
name Identifier of this declaration
category Kind of declaration (e.g. CG_PROCESS)
Optional information:
modifiers Set of modifiers (if any)
container Enclosing declaration (if any)
source Node of the AST where the declaration is performed (if any)
scope Symbol table with names declared inside this declaration (if any)
Each information defines methods hasInfo(), getInfo() and setInfo() e.g. : setModifiers(), getName()
Declarations: APIs
Additional methods allow us to get specific information from the declarations, without traversing the AST.
In PackageDecl:
In ObjectDecl
Visitors
Traversals of the AST use the Visitor design pattern:
“A solution to the problem of adding operations
to the elements of an object structure without
changing the classes on which it operates”
1 traversal = 1 Visitor class
AST classes not modified when adding new Visitors
The code of the traversal is divided in visit() methods: Object visitNameNode(NameNode node,
                       LinkedList args)
There is one _defaultVisit() method used if visit() method is not defined for a class of nodes
Back-end tool may need several traversals of the AST
® Back-end  tool = set of visitors + additional classes
Visitors
How to write a back-end?
How to write a back-end?
How to write a back-end?
How to write a back-end?
How to write a back-end?
How to write a back-end?
Slide 26
Writing a Visitor
Steps to Write a Visitor (1)
Steps to Write a Visitor (2)
Which traversal method to use?
Steps to Write a Visitor (3)
Structure of a Visitor (1)
File: MetaModelBackend.java
Structure of a Visitor (2)
   public Object visitCompileUnitNode
    }
What to do with a node? (1)
What to do with a node? (2)
Using TM_CUSTOM (1)
To traverse a list of nodes, use this static method:
ArrayList TNLManip.traverseList
(IVisitor visitor, LinkedList args, List list);
Using TM_CUSTOM (2)
To traverse only a node at one time, invoke this method on at TreeNode:
    Object accept(IVisitor visitor, LinkedList args);
Using TM_CHILDREN_FIRST
One useful method to retrieve the return values of the children nodes:
Object childReturnValueAt(int index);
MetaModelCodeGenVisitor.java
(EXAMPLE)
package metropolis.metamodel.backends.metamodel;
import metropolis.metamodel.*;
import metropolis.metamodel.nodetypes.*;
public class MetaModelCodegenVisitor extends MetaModelVisitor
        implements MetaModelStaticSemanticConstants{
 public MetaModelCodegenVisitor() {
        super(TM_CUSTOM);
    }
MetaModelCodeGenVisitor.java
public Object visitCompileUnitNode (CompileUnitNode node,
                                        LinkedList args) {
LinkedList retList = new LinkedList();
if (node.getPkg() != AbsentTreeNode.instance) {
            retList.addLast("package ");
            retList.addLast(node.getPkg().accept(this, args));
            retList.addLast(";\n");
      }
retList.addLast(TNLManip.traverseList(this, args, node.getImports()));
      retList.addLast("\n");
Iterator typeItr = TNLManip.traverseList
                        (this, args, node.getDefTypes()).iterator();
…
      return _stringListToString(retList);
}
Other Useful Methods
StringManip.java
Other Useful Methods (1)
To create a list containing one object: LinkedList TNLManip.addFirst(Object obj)