JastAdd
This is our old website.
Broken links can occur.
A new website is under construction.

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(...);
      ...
   }
   ...
}