|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
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. |
|
|
|
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
Example: annotate the AST of a file with the
number of classes declared
in that file. |
|
|
|
|
|
The front-end provides several annotations
with semantic information |
|
|
|
On the CompileUnitNode: information about the
file |
|
|
|
|
|
|
|
|
|
On other nodes: specific informations |
|
|
|
|
|
|
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. |
|
|
|
|
|
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() |
|
|
|
|
|
|
Additional methods allow us to get specific
information from the declarations, without traversing the AST. |
|
In PackageDecl: |
|
|
|
|
|
|
|
In ObjectDecl |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Which traversal method to use? |
|
|
|
|
|
|
File: MetaModelBackend.java |
|
|
|
|
public
Object visitCompileUnitNode |
|
|
|
} |
|
|
|
|
|
|
|
|
|
To traverse a list of nodes, use this static
method: |
|
ArrayList TNLManip.traverseList |
|
(IVisitor visitor, LinkedList
args, List list); |
|
|
|
|
|
To traverse only a node at one time, invoke this
method on at TreeNode: |
|
Object accept(IVisitor visitor, LinkedList args); |
|
|
|
|
|
One useful method to retrieve the return values
of the children nodes: |
|
Object childReturnValueAt(int index); |
|
|
|
|
(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); |
|
} |
|
|
|
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
|
To create a list containing one object: LinkedList
TNLManip.addFirst(Object obj) |
|