|
Aspects
JastAdd aspects support intertype declarations for AST
classes. An intertype declaration is a declaration that appears in an
aspect file, but that actually belongs to an AST class. The JastAdd
system reads the aspect files and weaves the intertype declarations
into the appropriate AST classes. AST classes are the classes defined
in the .ast files, and also the predefined classes ASTNode, List, and
Opt. See the page on .ast
files for further information on AST classes.
The kinds of intertype declarations that can occur in an aspect
include ordinary Java methods and fields, and attribute grammar
constructs like attributes, equations, and rewrites.
Index
Aspects and aspect files
An aspect file can contain import declarations and one or more
aspects, e.g.:
import java.lang.util.*;
aspect A {
abstract public void Stmt.m();
public void WhileStmt.m() { ... }
public void IfStmt.m() { ... }
...
}
aspect B {
private boolean Stmt.count = 0;
}
The aspect syntax is similar to AspectJ. But in contrast to
AspectJ, the aspects are not real language constructs. The JastAdd
system simply reads the aspect files and inserts the intertype
declarations into the appropriate AST classes. For example, the
method "m" and its implementations are inserted into classes Stmt,
WhileStmt, and IfStmt. And the declaration of the field "count" is
inserted into the class Stmt. Import declarations are inserted into
all AST classes for which there are intertype declarations in the
aspect. So, the import of java.lang.util.* is inserted into Stmt,
WhileStmt, and IfStmt. For a more detailed discussion on the
similarities and differences between JastAdd aspects and AspectJ, see
below.
The aspect names, e.g., A and B above, are not used for anything
when weaving the aspects. They can be regarded simply as a way to
name the purpose of the aspect. Similarly, the use of more than one
aspect construct inside an aspect file is only for convenience.It
allows the different parts of the aspect file to be individually
named.
.jadd and .jrag files
An aspect file can have the suffix .jadd or .jrag. The JastAdd
system does not differ between these two types of files, but we
recommend the following use:
- Use .jrag files for declarative aspects, i.e., where you add
attributes, equations, and rewrites to the AST classes
- Use .jadd files for imperative aspects, i.e., where you add
ordinary fields and methods to the AST classes
It is perfectly fine to not follow this convention, i.e., to mix
both imperative and declarative features in the same aspect, but we
try to follow the convention in our examples in order to enhance the
readability of a system.
Example imperative
aspect (.jadd)
Here is an example imperative aspect that adds pretty printing
behavior to some AST classes. Typically, this file would be named
PrettyPrinter.jadd:
aspect PrettyPrinter {
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
System.out.println(indent + "while " + getExp().pp(indent + " ") + " do");
getStmt().pp(indent + " ");
}
void IfStmt.pp(String indent) { ... }
...
}
Example declarative aspect (.jrag)
Here is an example declarative aspect that adds type checking to
some AST classes. Typically, this file would be named
TypeChecking.jrag:
import TypeSystem.Type;
aspect TypeChecking {
syn Type Exp.actualType();
inh Type Exp.expectedType();
eq LogicalExp.actualType() = Type.boolean();
eq IdUse.actualType() = decl().getType();
...
eq WhileStmt.getExp().expectedType() = Type.boolean();
syn boolean Exp.typeError() = ! (actualType().equals(expectedType());
}
Supported AOP features
|
Feature
|
Comment
|
|
intertype declaration of AST fields, methods, and
constructors.
|
See the prettyprinting example above. The declarations
are inserted into the corresponding AST classes by the AST
weaver. Any modifiers (public, private, static, etc.), are
interpreted in the context of the AST class. I.e., not as in
AspectJ where the public/private modifiers relate to the
aspect.
|
|
intertype declaration of attributes, equations, and
rewrites
|
See the type checking example above. For more details,
see the attribution
page.
Note that access modifiers (public, private, etc.) are
not supported for attributes. All declared attributes
generate public accessor methods in the AST classes.
|
|
declare additional interfaces for AST classes
|
E.g., in an aspect you can write
WhileStmt implements LoopInterface;
This will insert an "implements LoopInterface" clause in
the generated WhileStmt class.
|
|
declare classes and interfaces in an aspect
|
E.g., in an aspect you can write
interface I { ... }
class C { ... }
This is equivalent to declaring the interface and class
in separate ordinary Java files. The possibility to declare
them inside an aspect is just for convenience.
|
|
refine a method declared in another aspect
(This feature is available in JastAdd version R20051107 and later.)
|
Often, it is useful to be able to replace or refine methods declared in another aspect.
This can be done using a "refine" clause. In the following example, the aspect A
declares a method m() in the class C. In the aspect B, the method is replaced,
using a "refine" clause. This is similar to overriding a method in a subclass, but here
the "overridden" method is in the same class, just defined in another aspect.
Inside the body of the refined method, the original method can be called explicitly.
This is similar to a call to super for overriding methods.
aspect A {
void C.m() { ... }
}
aspect B {
refine A void C.m() { // similar to overriding
...
A.C.m(); // similar to call to super
...
}
}
Note that the refine clause explicitly states which aspect is refined (A in this case).
Additional aspects may further refine the method. For example, an aspect C can refine
the method refined in B.
|
Similarities and differences from
AspectJ
The aspect concept in JastAdd was developed in parallel to the
AspectJ development, and we are gradually adopting the AspectJ
syntax. In the future, we might implement a version of JastAdd that
builds directly on AspectJ.
The important similarity between JastAdd aspects and AspectJ
aspects is the intertype declarations. In addition, JastAdd aspects
support attribute grammar features which AspectJ does not. Note,
however, that JastAdd supports intertype declarations only for the
AST classes, not for classes in general like AspectJ. There are many
other features of AspectJ that are not supported in JastAdd,
e.g.:
- Fields and methods private to an aspect are not
supported.
- Declaration of additional parent classes is not
supported.
- Dynamic features like AspectJ's pointcuts or advice are not
supported.
Idiom for private fields and methods
As mentioned, JastAdd does not support fields and methods that are
private to an aspect. As a workaround idiom, such fields and methods
can be implemented as (non-private) static fields and methods in class ASTNode. As
an example, consider the pretty printer. We might want to
parameterize the prettyprinter so that it can pretty print on any
PrintStream object and not only on System.out. Here is how you could write
this in AspectJ and the corresponding JastAdd implementation:
|
AspectJ code
|
JastAdd code
|
aspect PrettyPrinter {
private PrintStream ppStream = null;
public void prettyprint(ASTNode n, PrintStream s) {
ppStream = s;
n.pp("");
ppStream = null;
}
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
...
ppStream.println(...);
...
}
...
}
|
aspect PrettyPrinter {
static PrintStream ASTNode.ppStream = null;
public void ASTNode.prettyprint(PrintStream s) {
ppStream = s;
pp("");
ppStream = null;
}
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
...
ppStream.println(...);
...
}
...
}
|
|