Subsections

Design overview

The code generator library consists of three main objects: a graph traverser class, a node handler interface, and a driver interface. Figure 4.2 shows the major components involved.

Graph traverser
The graph traverser class is responsible for visiting the nodes in a given graph. The traverser visits graph nodes in a depth-first manner; that is, all child nodes of a given graph node are visited before proceeding to a sibling node. While visiting the graph, the traverser sends out events about the objects it sees.
Node handler
The node handler interface receives graph traversal events from the traverser object, and performs some useful action with them. The node handler also sends user interface events to the driver as needed.
Driver
The driver interface receives events from the node handler and translates these events into user interface information.

Figure 4.2: Components of the code generator design pattern.

A fourth very important object is an abstract implementation of the node handler interface: the code generator base class. This abstract base class performs most bookkeeping tasks involved in code generation, such as maintaining a record of visited nodes, providing some standard information about the current node in the graph, interfacing with a template set, and determining when to write generated code to disk.

Finally, the entire code generator class hierarchy uses template sets for generating code from a given input graph. By deriving a Java class from the abstract CodeGenerator base class, and by creating or modifying a set of templates, it is relatively easy to create or modify a component code generator.

Two-layer visitor design pattern

The code generator library follows a general design pattern known as the visitor pattern. The visitor pattern means that a ``visitor'' object ``travels through'' an abstract space, like the nodes of an XML document or the elements of a linked list. As the visitor object travels, it communicates its observations to some other object. The other object then does something useful with the received observations.

For the code generation task, the ``space'' is a CCM metamodel graph, which is normally the result of parsing an input IDL3 source file. The visitor object travels to each node in the graph and sends events about these nodes to a node handler object. In turn, the node handler object transforms these events into some sort of generated code.

Just for comparison, note that the visitor pattern shows up in other software packages. For example, this visitor pattern is also used in Python and Java's SAX XML parser classes: An XML tree traverser object crawls through the XML elements in an input file, sending traversal events to a node handler. In fact, the similarity between the two tasks is what inspired the current code generator design.

The CCM Tools extend the visitor pattern by adding a second layer, that of the driver object: The node handler sends user interface events to the driver object, and the driver object translates these events into user interface activity. This permits the node handler objects to be agnostic about displaying status information to the user.

This separation of traversal, node handling, and user interface information allows for a smaller code base and more abstract graph handling. In addition, separating graph traversal from node handling allows for reuse of the traverser object. For example, to generate code for different component types with a single pass through a graph, one need only instantiate multiple node handler objects. Each node handler object can independently receive and interpret the traversal events from the graph traverser.

Similarly, separating the user interface from the node handling allows for reuse of the node handler objects: Any node handler object can use any front end, which results in easier adaptation to different user interface environments.

Code generator templates

None of the code generator objects could generate any code without templates. In the absence of a template set, the graph traverser would send graph traversal information to a code generator, but the generator would not have any way of converting that information into output code.4.1 So to allow for more flexible template maintenance and increased code reuse, the code generators in the CCM Tools package use template sets.

A template set is a collection of text files. These files are mostly written in the target code generation language. For example, templates could be written in C++, Java, or Python for generating code in these languages. In general, there is a template for each node type in the CCM metamodel. However, there is normally more than one instance of a given node type in a graph; for example, there is often more than one component defined in a source IDL3 file. The templates thus contain keys as placeholders for dynamically-generated information. The code generators load appropriate templates from disk when they receive certain graph traversal events, and periodically the generators replace template keys with information from the graph traversal process.

Template keys form a large part of the template system's functionality, so a large part of the following tutorials are devoted to explaining how they work. For now, consider a short example. The local C++ component generator uses a template set that is written in C++. The C++ templates have keys as placeholders for things like component and operation identifiers (%(Identifier)s); operation parameter information (%(MParameterDef)s); exception names (%(MExceptionDefName)s); C++ data types for parameters, operations, and structs (%(LanguageType)s); and so forth. In fact, these four types of keys each have different meanings to the code generator (see section 4.3.3).

The different meanings of the four key types, and the template substitution processes, are all explained in greater detail in the next two tutorials. The first tutorial concentrates on writing a new code generator (along with its associated template set). The second tutorial is a little less in depth; it simply gives some guidelines for maintaining an existing generator.

2003-11-09