Layering Extensions

The CArray extension we have created is a direct extension of Java 1.4. In practice, language extensions usually build on other extensions. For example, Jif builds on Java 1.4, while Fabric builds on Jif. This last section of the tutorial shows that extending an already existing extension is as equally easy as extending the base language. In fact, we will describe the process to make our implementation of CArray extend Java 5 or Java 7 instead.
For convenience, we will use the term existing extension to denote the language extension to be extended, the term base language to denote the language without any extension, i.e., Java 1.4 for Polyglot, and the term higher-order extension to denote the language extension that extends the existing extension. There are only few differences when extending an existing extension rather than the base language: These changes are illustrated with CArray for the remainder of this section.

Extending the grammar of an existing extension

In addition to extending a CUP file, PPG supports extending a PPG file. The first line of a PPG file designates the grammar to be extended. Here is one from carray.ppg that extends Java 1.4 grammar:
include "polyglot/parse/java12.cup"
To change CArray to extend Java 5 grammar, the above line is changed to
include "polyglot/ext/jl5/parse/jl5.ppg"
and the following to extend Java 7 grammar:
include "polyglot/ext/jl7/parse/jl7.ppg"
The definition of nonterminals usually also needs change when changing the base extension. This change is often nontrivial as is left as a challenging exercise. For instance, the array type must take generics into account.

Extending the language dispatcher of an existing extension

Changing the base extension entails changing the language dispatcher that the higher-order extension will extend. That is, instead of this class declaration for Java 1.4:
public class CArrayLang_c extends JLang_c implements CArrayLang {
    // ...
}
we use this class declaration to extend Java 5:
public class CArrayLang_c extends J5Lang_c implements CArrayLang {
    // ...
}
and this one to extend Java 7:
public class CArrayLang_c extends J7Lang_c implements CArrayLang {
    // ...
}

Extending the scheduler of an existing extension

Changing the scheduler is similar to changing the language dispatcher to be inherited from. That is, instead of this class declaration for Java 1.4:
public class CArrayScheduler extends JLScheduler {
    // ...
}
use this class declaration to extend Java 5:
public class CArrayScheduler extends JL5Scheduler {
    // ...
}
and this one to extend Java 7:
public class CArrayScheduler extends JL7Scheduler {
    // ...
}
It is possible that an existing extension might not have a scheduler associated with it. In this case, the existing extension must inherit a scheduler from its base extension, and the higher-order extension can safely extend that scheduler instead.

Modifying extension information

The only change to be made is to chain the extension factories differently by nesting the extension factories of all the extensions that the higher-order extension depends on, in order of layering. This chain of extension factories is passed as an argument to the constructor for the higher-order extension's node factory. This change is made in the implementation of createNodeFactory. For CArray, instead of this implementation when extending Java 1.4:
    @Override
    protected NodeFactory createNodeFactory() {
        return new CArrayNodeFactory_c(CArrayLang_c.instance,
                                       new CArrayExtFactory_c());
    }
use this implementation to extend Java 5:
    @Override
    protected NodeFactory createNodeFactory() {
        return new CArrayNodeFactory_c(CArrayLang_c.instance,
                                       new CArrayExtFactory_c(
                                           new JL5ExtFactory_c()));
    }
and this one to extend Java 7:
    @Override
    protected NodeFactory createNodeFactory() {
        return new CArrayNodeFactory_c(CArrayLang_c.instance,
                                       new CArrayExtFactory_c(
                                           new JL7ExtFactory_c(
                                               new JL5ExtFactory_c())));
    }
Last but not least, there can be conflicting semantic changes when switching the base extension. Careful scrutiny and thorough testing will help resolve these conflicts. Nevertheless, this is typically not a problem if a higher-order extension has been designed to extend a particular existing extension from the beginning.

Valid HTML 4.01 Transitional Valid CSS!