All Packages Class Hierarchy This Package Previous Next Index
java.lang.Object | +----epp.Macro
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.
 
 Macro()
	Macro()
   
 addTree(Symbol, Tree)
	addTree(Symbol, Tree)
   call(Tree)
	call(Tree)
   checkArgsLength(Tree, int)
	checkArgsLength(Tree, int)
   error(String)
	error(String)
   genTemp(String)
	genTemp(String)
   macroExpand1(Tree)
	macroExpand1(Tree)
   macroExpandArray(Tree[])
	macroExpandArray(Tree[])
   macroExpandTree(Tree)
	macroExpandTree(Tree)
   
 Macro
Macro
public Macro()
 
 call
call
public abstract Tree call(Tree tree)
 macroExpandTree
macroExpandTree
public static Tree macroExpandTree(Tree tree)
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.)
 macroExpand1
macroExpand1
public static Tree macroExpand1(Tree tree)
 macroExpandArray
macroExpandArray
public static Tree[] macroExpandArray(Tree args[])
 checkArgsLength
checkArgsLength
 public static void checkArgsLength(Tree tree,
                                    int argc)
error method is called.
 addTree
addTree
 public static void addTree(Symbol sym,
                            Tree tree)
  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 :afterCurrentBlockStatementWith 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.
 genTemp
genTemp
public static Symbol genTemp(String prefix)
  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.
 error
error
public static Error error(String str)
EppUserError.
Its usage is the same as EppCore#error.
All Packages Class Hierarchy This Package Previous Next Index