PJ

PJ is a new tool for JTS specifically written to support the GenBorg model. PJ compacts extension chains for classes, interfaces., and state diagrams To call PJ:

> java PJ.Main [-tk] <base-file-name> <extension-file-name>

where:

The Bali command to build PJ is:

> java Bali.Main PJ

The layers that are included in PJ, along with a description of their semantics, is briefly below:

The following topics are covered in this document:

Purpose

The GenBorg model produces a set of equations that define the extension chains or extension hierarchies of generated files. An equation r = a(b(c)) means compose base class or interface c with extension b, and that with extension a to produce r. PJ flattens this extension chain to produce a single file.  If this composition were to be performed via a command-line, you would write:

> java PJ.Main -tk c.java b.java > tmp.java
> java PJ.Main -tk tmp.java a.java > result.java

This isn't the preferred way to do this composition, for several reasons.  First, PJ annotates parse trees with information that is lost when outputting intermediate results to files.  This information isn't critical for running the current stable of regression tests, but will be very important later on.  Second, the above runs slowly.

The preferred way is via a programmatic means:

import PJ.*;
// Step 1: set the -t and -k flags in PJ
Lang.JTSParseTree.setFlags( true, true ); // set the -t and -k flags in PJ
// Step 2: create parse trees for files a, b, and c

Lang.JTSParseTree a = new Lang.JTSParseTree( "a.java" );
Lang.JTSParseTree b = new Lang.JTSParseTree( "b.java" );
Lang.JTSParseTree c = new Lang.JTSParseTree( "c.java" );
// Step 3: compose the trees, a.compose(b) merges b into a 
//         so a is modified
a.compose(b);
a.compose(c);
// Step 4: set package name. The produced file will be
//         in package "foo", and output the file.

a.setPackageName("foo");
a.print2file( "abc.java");

The above calling sequence will be used in GUI tools that take GenBorg equations, expand them, and invoke the corresponding extension-hierarchy compaction tools (of which PJ will be the tool for compacting code chains).

insert chapters here

How to call PJ from the Command Line

Use the following to invoke PJ from the command line:

> java PJ.Main -tk Basefile Extension1file Extension2file ... > output

The option -t selects type sorting, -k selects key sorting.  The resulting output (error messages and all) are sent to standard out.

How to call PJ from a Program

PJ is a package that can be called from another program (i.e., tool) in the following way.

(a) set PJ flags, clear error and warning counters, and specify the destination of error and warning messages:

PJ.JTSParseTree.setFlags( true, true );
PJ.JTSParseTree.resetCounters();
JTSParseTree.setReportStream( new PrintWriter( System.out ) );

(b) create a JTSParseTree for each file, such as below:

try {
   PJ.JTSParseTree base = new PJ.JTSParseTree( "base-file-name" );
   PJ.JTSParseTree ext  = new PJ.JTSParseTree( "extn-file-name" );
}
catch (Exception e) {
   System.err.println( "can't parse or open base or extension files" 
                       + e.getMessage() );
}

(c) compose the trees, as below:

try {
   base.compose( ext );
   if (PJ.JTSParseTree.errorCount() == 0) {
      // composition succeeded
   } else {
      // composition failed -- error string appears in reportStream PrintWriter
   }
}
catch (Exception e) {
   System.err.println( e.getMessage() );
   // fatal error occurred in composition; something is likely wrong with PJ
}

note: compose can throw a RuntimeException if there are fatal errors; do not try to perform further compositions beyond this point.  Composition errors can result, but exceptions will not be thrown.

(d) after all required files have been composed, set the name of the package for the generated class.

base.setPackageName( "name-of-package" );

(e) output the resulting file.  This can be done by any one of several methods:

As an example:

base.print();

Regression Tests

In regression/PJ you will find regression tests for interfaces and classes.  To run the entire suite of tests type:

> bash regress

Limitations, Future Versions and Known Problems

PJ currently understands extensions to Java classes, interfaces, and state diagrams. It does not yet understand other extensions that have been added to Java, such as AST constructors.  Extending PJ to support most of these features should be very simple.

To extend PJ, every AST_FieldDecl and TypeDeclaration production of the Java grammar must support a compose method. See the preprocess, CompInt, CompClass, and CompSm layers for details.

Another limitation variable capture.  For now, this means that programmers must be very careful in selecting the names of variables and methods so that there is no name collision.  More on this later.

PJ is still undergoing changes.  Known problems include: