All Packages  Class Hierarchy  This Package  Previous  Next  Index

Class epp.Macro

java.lang.Object
   |
   +----epp.Macro

public abstract class Macro
extends Object
The Macro class is the super class of the class of all macro expansion objects.

Within the syntax macro expansion pass, each node of the abstract syntax tree is checked to see if it is a macro node, and if so, the call method of the corresponding macro expansion object is called.

When a plug-in programmer introduces a node that was not included in standard Java, the programmer must also provide a class of a "macro expansion object" that will convert the node into a standard Java node. Furthurmore, the newly defined macro expansion object must be registered with the macro expansion object table using the Epp method defineMacro. For example, in the source code of the enum plug-in, an expansion object that expands a tree that has a tag named :enum is registered as follows. (The EnumMacro class is a subclass of class Macro.)

    extend void initMacroTable() {
      original();
      defineMacro(:enum, new EnumMacro());
    }

The macro expansion object is an instance of a subclass of class Macro. The macro expansion object has a method named call, that accepts a tree as an argument and returns a tree.

The macro expansion object can be expanded using a decorator pattern. In order to do so, you use Epp's extendMacro method. The original macro expansion object can be called from the decorator via the instance variable orig. The value of the variable orig is null if it is not expanded by extendMacro.

The recursive macro expansion of a tree is done by the macroExpandTree method. The behaviour of the macroExpandTree method is strictly defined as follows.

      Symbol lastTag = null;
      while(true) {
        Symbol tag = tree.tag();
        if (tag == lastTag) break;
        lastTag = tag;
        Macro func = (Macro)macroTable.get(tag);
        if (func != null) {
          tree = func.call(tree);
        } else {
          tree = tree.modifyArgs(macroExpandArray(tree.args()));
        }
      }
      return tree;
That is, it calls the call method of the macro expansion object corresponding to the tag of the tree, and if the returned tag and the tag prior to calling the method match, it exits the loop and returns the returned value. Otherwise, it keeps on converting the macro expansion until the tag does not change any further. If a macro expansion function corresponding to the tag of the node does not exist, it creates a node with its own subtree replaced with a macro expanded one, and returns that node.

A class named InvokeStyleMacro is provided to make it easier to define a macro that has the same grammar as a method call.

See Also:
initMacroTable, defineMacro, extendMacro, TypeChecker, InvokeStyleMacro

Constructor Index

 o Macro()

Method Index

 o addTree(Symbol, Tree)
Adds tree to a dynamic variable.
 o call(Tree)
Defines a method that expands the macro of a tree within a subclass.
 o checkArgsLength(Tree, int)
Checks the number of arguments of the node.
 o error(String)
Called when an error occured while expanding a macro.
 o genTemp(String)
Called to generate a unique identifier when expanding macros.
 o macroExpand1(Tree)
Expands a macro only once.
 o macroExpandArray(Tree[])
Expands each element of the argument array and returns the result in a new array.
 o macroExpandTree(Tree)
Expands recursively all macros.

Constructors

 o Macro
 public Macro()

Methods

 o call
 public abstract Tree call(Tree tree)
Defines a method that expands the macro of a tree within a subclass.

 o macroExpandTree
 public static Tree macroExpandTree(Tree tree)
Expands recursively all macros. Retrieves a registerd macro expansion object from Macro.macroTable using the tag of the argument tree as the key. If the object exists, it calls it, and otherwise executes the default macro expansion.

You may call this method explicitely from within a macro expansion object that a plug-in programmer defines, but in most cases will need to do so. (The tree returned by the call method of the macro expansion object is expanded automatically until all internal macros are expanded.)

 o macroExpand1
 public static Tree macroExpand1(Tree tree)
Expands a macro only once. Calls the macro expansion object corresponding to the tag of the argument tree and returns the result. Use this to check the behaviour of macro expansion objects when debugging.

 o macroExpandArray
 public static Tree[] macroExpandArray(Tree args[])
Expands each element of the argument array and returns the result in a new array.

 o checkArgsLength
 public static void checkArgsLength(Tree tree,
                                    int argc)
Checks the number of arguments of the node. If the the length of the args of tree is not equal to argc, the error method is called.

 o addTree
 public static void addTree(Symbol sym,
                            Tree tree)
Adds tree to a dynamic variable. This method is defined as follows.
  public static void addTree(Symbol sym, Tree tree){
    TreeVec tvec = (TreeVec)Dynamic.get(sym);
    tvec.add(macroExpandTree(tree));
  }

For example, you may want to add a method to the class currently expanding while executing macro expansion for an expanded syntax. In order to do so, you may write the following.

    addTree(:beginningOfClassBody,
    	    aMethodDeclarationTree);
The following symbols can be specified as the first argument to addTree.
	:beforeCurrentTypeDeclaration
	:afterCurrentTypeDeclaration
	:beginningOfClassBody
	:beforeCurrentClassBodyDeclaration
	:afterCurrentClassBodyDeclaration
	:beforeCurrentBlockStatement
	:afterCurrentBlockStatement
With these, you can add code to the top level of the current file, add instance variables and methods to the current class, add local type declarations immediately before the current statement, add post-processing immediately after the current statement, etc.

See Also:
Dynamic
 o genTemp
 public static Symbol genTemp(String prefix)
Called to generate a unique identifier when expanding macros. This method is defined as the following.
  public static Symbol genTemp(String prefix){
    return Symbol.intern(prefix + genTempCounter++);
  }

Where genTempCounter is a static variable with an initial value of 0. Initialization is done only once when EPP is invoked.

 o error
 public static Error error(String str)
Called when an error occured while expanding a macro. Returns an instance of class EppUserError. Its usage is the same as EppCore#error.

See Also:
error

All Packages  Class Hierarchy  This Package  Previous  Next  Index