Explore Java Infrastructure
Pt
In this course, we will use Java as the object language, i.e. the programs that we are going to transform are written in Java. Of course, you are all familiar with Java and its
concrete syntax, but you might not be that familiar with the
abstract syntax of the Java language. Before starting with the real transformation assignments, it is a good idea to explore this structure a bit.
Java Syntax
The tool
parse-java is used to parse Java programs to an abstract syntax tree represented as an ATerm. Begin with a very simple Java class:
$ echo "class Foo {}" | parse-java | pp-aterm
You can also put the class in a file, which is useful if you are going to try bigger examples. For files, use
parse-java -i File.java.
Try to find the corresponding SDF productions in the Java syntax definition (see the navigation bar for a link). Also, lookup these definitions in the Java Language Specification (JLS), which should be easy: the paragraphs of the JLS are mentioned in the syntax definition.
Next, extend the Java program with various code to find out what all these empty lists and Nones are about. For example, introduce an import of
java.util.List, declare a package, add a method with some simple statements, let the class extend another class etc. If something is unclear, then lookup the productions in the syntax definition.
Java-front also features a pretty-printer for Java. You can apply this pretty-printer in a pipeline with the parser:
$ parse-java -i Foo.java | pp-java
Java Bytecode
Compile a simple Java source file to a .class file and decompile it using the tool
class2aterm:
$ class2aterm -i Foo.class | pp-aterm
Take a brief look at the structure of this aterm. This invocation does not disassemble the code. For this, you have to pass
-c as an argument to class2aterm:
$ class2aterm -i Foo.class -c | pp-aterm
Most likely, you will not directly use this tool, but it is good to know that it exists. You will use it a lot indirectly, since the Dryad reflection library uses class2aterm to disassemble Java classes. Dryad also supports a bytecode assembler:
$ class2aterm -i Foo.class -c | aterm2class -o Bar.class
Java Disambiguation
Although you might have the impression that a statement like
System.out.println("Hi!") is very clear, it is actually very ambiguous, syntactically speaking. Parse a small Java source file containing this hello world statement and take a look at the representation. Obviously, this representation does not tell us much about the meaning of this program. Therefore, it is difficult to transform this program directly: you cannot just assume a certain meaning for all these ambiguous names.
The Java Language Specification specifies how all ambiguous names should be interpreted (see for example
JLS 6.5.2: Reclassification of Contextually Ambiguous Names). To make the implementation of Java transformations more reliable, Dryad implements this reclassification and qualification of names.
Use the tool dryad-front to reclassify the names:
$ dryad-front -i HelloWorld.java | pp-aterm
Take a close look at this example and observe the reclassified names and the qualifiers that have been added to all the names (for example,
System is now qualified with
java.lang).
In most assignments, we will work on this reclassified and qualified representation of a Java program. Try a few other samples. For example, add an import declaration and find out what happens with local variable and field accesses. Dryad-front accepts multiple source files, but you can also use multiple classes in the same source file of course. Example:
$ dryad-front -i Foo.java Bar.java -o Foo.jtree Bar.jtree
You cannot apply pp-aterm after this invocation (it produces multiple aterms, which is not supported by other tools), that's why output files are used.
Java Type Information
Dryad also provides a type checker, which annotates the expressions of a Java program with their type. The type checker can be enabled by adding the command-line option --tc on:
$ dryad-front --tc on -i HelloWorld.java | pp-aterm
Try a few different examples of method invocations, operators, etc. Note that the type checker does not only annotate types, but also conversions and information about the declaring classes of fields and method accesses. Try an example of a method invocation that invokes a method that is declared in a superclass of the object on which the method is invoked and see what happens with the annotation.
Dryad Model for Java
Exploring the Dryad Model requires some basic knowledge of Stratego, so we will do this later.
See Also