Stratego / STRJ

Stratego -- Strategies for Program Transformation
STRJ compiles Stratego to Java, and is a Java-based variation of the Stratego Compiler.

Introduction

The compiler comes in two flavors: one called strj, compiled with the standard C-based strc. The second is a bootstrapped, cross-platform compiler that lives in strategoxt.jar. Note that Stratego executables compiled with strj do not support XTC (since it depends on forking native executables and assumes filesystem access) and the strategoxt.jar compiler is no exception. Another difference between the two is that strj still uses the C-based SGLR parser, and strategoxt.jar uses JSGLR.

Compiling a simple application from the command line with either compiler is similar to doing so with the strc command:

  strj -i foo.str -la stratego-lib

or

  java -jar strategoxt.jar -i foo.str -la stratego-lib

It should be noted that at this time the compiler only outputs .java source files and not .class files. Subsequent compilation should be done using a standard Java compiler (ideally, in an automated fashion using an Ant build script or Eclipse). The (non-portable) strj-jar shell script can also help with command-line or scripted builds.

Known Issues

The Stratego/J runtime implements most of the primitives of the natively compiled version of Stratego, but some compatibility issues may arise. In particular, the parsing primitives are implemented using JSGLR, the Java version of SGLR, which is not yet fully mature. This especially impacts the heuristic filters, which are disabled by default, but used for Stratego's concrete syntax embedding. To work around any problems, we suggest using the native strj executable to compile these files for now, or to pre-parse them to .rtree files using parse-stratego. A general recommendation may be to disable the heuristic filters in the .meta files using the HeuristicFilters(Off()) directive.

The standard Sun compiler can be quite slow when compiling large Stratego projects. We recommend using ECJ (Eclipse Compiler for Java) instead, which is much faster and less memory-intensive. ECJ is distributed as part of Eclipse, and can be executed as follows:

  java -cp plugins/org.eclipse.jdt.core_*.jar  org.eclipse.jdt.internal.compiler.batch.Main

Many Linux distributions also provide a stand-alone version of ECJ through their package manager. (Note that ECJ 3.3 and lower have a bug that can be worked around with the -Xecj33 flag.) When using the Sun compiler, you may need to add option -J-mx256m to increase the available heap space, and likely need to have a fair amount of patience ;)

Stratego programs compiled to Java do not have the same performance characteristics as those compiled using the native Stratego compiler strc. The exact numbers vary per application (some, such as the somewhat artificial ASF+SDF benchmark, actually run faster on Java), but natively compiled Stratego applications that include parsing and pretty-printing are typically a factor two faster. Future optimizations, particularly in the term library and in I/O, may make this gap smaller.

A final open issue is the stack usage by typical Stratego programs, putting JVM implementations with a small default stack size at risk of throwing a StackOverflowException (notably the Sun JVM on Linux). For these systems, running the JVM with option -ss4m avoids the stack overflow problem. (When this parameter is not set and a stack overflow occurs, compiled applications will hint at this setting.)

While the XTC standard library strategies (such as xtc-io-wrap) are supported, support for the XTC repository is not implemented as this time because of portability concerns. Any xtc-transform or xtc-call invocations report a warning, and simply invoke executables on the path. For the interest of portability, applications that make use of these strategies should use library strategies instead, as discussed in the following section.

Using External Applications and Libraries

A trend in Stratego programs has been to use the standard libraries in favor of the (slower, less portable) XTC interface. For example, the parse-file strategy from libstratego-sglr can be used to parse files. Since XTC depends on native executables and a centralized repository, it is not portable and not supported on the Java platform. As an alternative, library calls should be used instead, which is generally the preferred method for invoking external components.

Libraries in the Java environment have a package name. For example, the Stratego standard library resides in the org.strategoxt.stratego_lib package. To maintain compatibility, these package names are not used within the Stratego language, but only at compile time and when the components are linked. For example, to link a program to the standard library the option -la org.strategoxt.stratego_lib can be specified. The standard libraries also have aliases that correspond to the XTC names commonly used with strc; -la stratego-lib is also accepted. To define a package name for your own library, use the -p and --library options. For example:

  java -jar strategoxt.jar -i foo.str --library --clean -p org.foo -o bin/org/foo/Main.java

Note that each Stratego component may specify a different main class (Main in this case), but that they must still reside in different packages as to avoid overlap between strategy classes.

Java Integration

A typical use case of compiling Stratego applications to Java is to integrate them into an existing Java application or environment. Interaction with the other Java components is possible in a number of ways:

  • Java components can directly call Stratego strategies, by calling the Main.init() method in the appropriate package and invoking a Strategy using some_strategy_0_0.instance.invoke(). If the exit strategy is called at any point, a StrategoExit exception will be thrown; a call to fatal-err will throw a StrategoErrorExit exception.

  • Normal Java components can be used to implement or override Stratego strategies, allowing for tighter coupling between Stratego and a Java application. See for example https://svn.strategoxt.org/repos/StrategoXT/ strc-java/trunk/java/runtime/org/strategoxt/lang/compat/libstratego_rtg_compat where two strategies (originally implemented natively in C) are implemented in Java. Every strategy has an instance field that allows it to be dynamically redefined.

  • Compiled Stratego components can be dynamically loaded from JAR files and may be combined with interpreted components using the HybridInterpreter class. To interpret a Stratego component, pre-compile it to a .ctree file using STRJ and the -F --library options.

Download

Native builds of the Jompiler ("strc-java") are available from Hydra:

the pure Java version (included in the above distribution) can also be downloaded from:

The Java version of STRJ is also integrated in the Spoofax plugin that allows you to develop languages and Eclipse plugins with Stratego.

Project Information

Source Code

Source code is available directly from SVN at

or can be downloaded as a package at hydra.nixos.org.

Contributors

Contributors

  • Lennart Kats (main STRJ development and maintainer; Stratego/J compatibility components)
  • Karl Trygve Kalleberg (main Stratego/J and JSGLR development; original s2j prototype)
  • Valentin David (parts of the Stratego/J runtime)

The development of STRJ would not have been possible without the efforts of Eelco Visser and his team in developing the STRC reference stratego compiler. Martin Bravenboer's Java-front library and syntax definition have also been indispensable for the development STRJ.

License

STRJ is licensed under the GNU Lesser General Public License (LGPL).

Contact and Mailing List

Please send questions to the users@strategoxt.org mailing list or contact Lennart Kats directly. Also, we can usually be found online on IRC at #stratego on freenode.net (web version). Feel free to drop by!

Related Software

The Spoofax/IMP IDE development environment incorporates the STRJ compiler. By default, it interprets Stratego definitions, using the hybrid interpreter, but by changing the build.xml and <myproject>-Analysis.esv files, it can also compile them.