Class TreeNode

java.lang.Object
  extended byTreeNode
Direct Known Subclasses:
Case, Class_, Expression, Feature, Formal, ListNode, Program

abstract class TreeNode
extends java.lang.Object

The base class for all AST nodes. After lexical analysis and parsing, a Cool program is represented internally by the Cool compiler as an abstract syntax tree. The project comes with a definition of Cool abstract syntax trees (ASTs) built in. The AST package is by far the largest piece of code in the base system and requires the most time to learn. The learning process is made more complex because the AST code is generated automatically from a specification in the file cool-tree.aps. While the generated code is quite simple and regular in structure, it is also devoid of comments. This section serves as the documentation for the AST package.

Phyla and Constructors

The AST data type provides a class for representing each type of Cool expression. There is a class for let expressions, another class of + expressions, and so on. Objects of these classes are nodes in Cool abstract syntax trees. For example, an expression e1 + e2 is represented by a + expression object, which has two subtrees: one for the tree representing the expression e1 and one for the tree representing the expression e2.

The Cool abstract syntax is specified in a language called APS. In APS terminology, the various kinds of abstract syntax tree nodes (let, +, etc.) are called constructors. (Don't confuse this use of the term "constructor" with Java constructors; while similar, this is a slightly different meaning taken from functional languages that predates Java.) The form of the AST is described by a set of phyla. Each phylum has one or more constructors.

Phyla are really just types. That is, instead of having one large group of undifferentiated constructors, the constructors are grouped together according to function, so that, for example, the constructors for expression ASTs are distinguished from the constructors for class ASTs. The phyla are defined at the beginning of cool-tree.aps:

  module COOL begin phylum
  Program;

  phylum Class_;
  phylum Classes = LIST[Class_];

  phylum Feature;
  phylum Features = LIST[Feature];

  phylum Formal;
  phylum Formals = LIST[Formal];

  phylum Expression;
  phylum Expressions = LIST[Expression];

  phylum Case;
  phylum Cases = LIST[Case];
From the definition it can be seen that there are two distinct kinds of phyla: "normal" phyla and list phyla. "Normal" phyla each have associated constructors; list phyla have a fixed set of list operations.

Each constructor takes typed arguments and returns a typed result. The types may either be phyla or any ordinary Java type. In fact, the phyla declarations are themselves compiled into Java class declarations by an APS compiler. A sample constructor definition is

  constructor class_(name : AbstractSymbol; 
                     parent : AbstractSymbol;
                     features : Features; 
                     filename : AbstractSymbol) : Class_;
This declaration specifies that the class_ constructor takes four arguments: an AbstractSymbol (a type identifier) for the class name, an AbstractSymbol (another type identifier) for the parent class, a Features, and an AbstractSymbol for the filename in which the class definition occurs. (the name class_ is chosen to avoid a conflict with the Java keyword class.) The phylum Features is defined to be a list of Feature's by the declaration
    phylum Features = LIST[Feature];
See ListNode for a description of the operations defined on AST lists.

To invoke the class constructor, you allocate a new node object supplying it with the right arguments, e.g. new class_(...). In cool.cup there is the following example of a use of the class_ constructor:

class	::= CLASS TYPEID:n INHERITS TYPEID:p LBRACE optional_feature_list:f RBRACE SEMI
        {: RESULT = new class_(curr_lineno(), n, p, f, curr_filename()); :}
Allocating a new class_ object, builds a tree node with the four arguments as children. Because the phyla (types) of the arguments are declared, the Java type checker enforces that the class_ constructor is applied only to arguments of the appropriate type. See Section 6.5 of the "Tour of Cool Support Code" and cool-tree.aps to learn the definitions of the other constructors. (Comments in cool-tree.aps begin with two hyphens "--".)

NOTE: there is a real danger of getting confused because the same names are used repeatedly for different entities in different contexts. In the example just above, small variations of the name class are used for a terminal (CLASS), a non-terminal (class), a constructor (class_), and a phylum (Class_). These uses are all distinct and mean different things. Most uses are distinguished consistently by capitalization, but a few are not. When reading the code it is important to keep in mind the role of each symbol.

The AST Class Hierarchy

All AST classes are derived from this class (TreeNode). (The list classes are actually derived from ListNode, which is a refinement of TreeNode.) All of the lists are lists of TreeNodes.

The TreeNode class definition contains everything needed in an abstract syntax tree node except information specific to particular constructors.

Each of the constructors is a class derived from the appropriate phyla.

Class Members

Each class definition of the tree package comes with a number of members. Some of the member functions are discussed below. This section describes the data members and some more (but not all) of the rest of the functions, as well as how to add new members to the classes. Each constructor has data members defined for each component of that constructor. The name of the member is the name of the field in the constructor, and it is only visible to member functions of the constructor's class or derived classes. For example, the class_ constructor has four data members:
Symbol name;
Symbol parent;
Features features;
Symbol filename;
Here is a complete use of one member:
 class class_ extends Class_ {
     ...
     AbstractSymbol getParent() { return parent; }
     ...
 }

 ...

 Class_ c;
 AbstractSymbol p;

 c = new class(lineno, AbstractTable.idtable.add_string("Foo",3),
                       AbstractTable.idtable.add_string("Bar"), 
                       new Features(lineno),
                       AbstractTable.stringtable.add_string("filename"));
 p = c->get_parent();  // Sets p to the symbol for "Bar"

 ...
It will be useful in writing a Cool compiler to extend the AST with new functions such as getParent(). Simply modify the cool-tree.java file to add functions to the class of the appropriate phylum or constructor.

Tips on Using the Tree Package

There are a few common errors people make using a tree package.


Field Summary
protected  int lineNumber
          line in the source file from which this node came.
 
Constructor Summary
protected TreeNode(int lineNumber)
          Builds a new tree node
 
Method Summary
protected  AbstractSymbol copy_AbstractSymbol(AbstractSymbol sym)
          Copies an AbstractSymbol value.
protected  java.lang.Boolean copy_Boolean(java.lang.Boolean b)
          Copies a boolean value.
abstract  TreeNode copy()
          Creates a copy of this node.
protected  void dump_AbstractSymbol(java.io.PrintStream out, int n, AbstractSymbol sym)
          Dumps a printable representation of an AbstactSymbol value.
protected  void dump_Boolean(java.io.PrintStream out, int n, java.lang.Boolean b)
          Dumps a printable representation of a boolean value.
protected  void dump_line(java.io.PrintStream out, int n)
          Dumps a printable representation of current line number This method is used internally by the generated AST classes
abstract  void dump(java.io.PrintStream out, int n)
          Pretty-prints this node to this output stream.
 int getLineNumber()
          Retreives the line number from which this node came.
 TreeNode set(TreeNode other)
          Sets the values of this node object to the values of a given node.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

lineNumber

protected int lineNumber
line in the source file from which this node came.

Constructor Detail

TreeNode

protected TreeNode(int lineNumber)
Builds a new tree node

Parameters:
lineNumber - the line in the source file from which this node came.
Method Detail

copy

public abstract TreeNode copy()
Creates a copy of this node.

Returns:
a copy of this node

set

public TreeNode set(TreeNode other)
Sets the values of this node object to the values of a given node.

Parameters:
other - the other node
Returns:
this node

getLineNumber

public int getLineNumber()
Retreives the line number from which this node came.

Returns:
the line number

dump

public abstract void dump(java.io.PrintStream out,
                          int n)
Pretty-prints this node to this output stream.

Parameters:
out - the output stream
n - the number of spaces to indent the output

copy_Boolean

protected java.lang.Boolean copy_Boolean(java.lang.Boolean b)
Copies a boolean value. This method is used internally by the generated AST classes


copy_AbstractSymbol

protected AbstractSymbol copy_AbstractSymbol(AbstractSymbol sym)
Copies an AbstractSymbol value. This method is used internally by the generated AST classes


dump_Boolean

protected void dump_Boolean(java.io.PrintStream out,
                            int n,
                            java.lang.Boolean b)
Dumps a printable representation of a boolean value. This method is used internally by the generated AST classes


dump_AbstractSymbol

protected void dump_AbstractSymbol(java.io.PrintStream out,
                                   int n,
                                   AbstractSymbol sym)
Dumps a printable representation of an AbstactSymbol value. This method is used internally by the generated AST classes


dump_line

protected void dump_line(java.io.PrintStream out,
                         int n)
Dumps a printable representation of current line number This method is used internally by the generated AST classes