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.