To promote retargetable code generators, ST supports interface implementation a la Java interfaces where a template group that implements an interface must implement all templates in the interface and with the proper argument lists. The interface is the published, executable documentation for building back-ends for the code generator and has proven to be an excellent way to inform programmers responsible for the various targets of changes to the requirements.
The developers of the ANTLR code generation targets always have the same two questions: Initially they ask, "What is the set of templates I have to define for my target?'' and then, during development, they ask, "Has a change to the code generation logic forced any changes to the requirements of my template library?"
Originally, the answer to the first question involved abstracting the list of templates and their formal arguments from the existing Java target. The answer to the second question involved using a difference tool to point out changes in the Java target from repository check-in to check-in. Without a way to formally notify target developers and to automatically catch logic-template mismatches, bugs creep in that become apparent only when the stale template definitions are exercised by the code generator. This situation is analogous to programs in dynamically typed languages like Python where method signature changes can leave landmines in unexercised code. In short, there were no good answers.
ST now supports group interfaces that describe a collection of template signatures, names and formal arguments, in a manner analogous to Java interfaces. Interfaces clearly identify the set of all templates that a target must define as well as the attributes they operate on. The first question regarding the required set of templates now has a good answer.
Interfaces also provide a form of type safety whereby a target is examined upon code generator startup to see that it satisfies the interface. Here is a piece of the ANTLR main target interface:
parser(name, scopes, tokens, tokenNames, rules,
numRules, cyclicDFAs, bitsets, ASTLabelType,
superClass, labelType, members);
rule(ruleName, ruleDescriptor, block, emptyRule,
/** What file extension to use; e.g., ".java" */
All of the various targets then implement the interface; e.g.,
group Java implements ANTLRCore;
The code generator, which loads target templates, notifies developers of any inconsistencies immediately upon startup effectively answering the second question regarding notification of template library changes. Group interfaces provide excellent documentation, promote consistency, and reduce hidden bugs.
Interfaces look exactly like groups except that they don't have template implementations for the template declarations although they must have the complete parameter list. Further, a template may be defined as optional using the
optional headerFile(actionScope, actions, docComment, recognizer, ...);