All Packages  Class Hierarchy  This Package  Previous  Next  Index

Class epp.Macro

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

public abstract class Macro
extends Object
クラス Macro は、すべてのマクロ展開オブジェクトのクラスの スーパークラスです。.

構文マクロ展開パスにおいて、抽象構文木の各ノードは マクロノードかどうかチェックされ、もしそうならば、 対応するマクロ展開オブジェクトのメソッド "call" が呼び出されます。

plug-in programmer は、標準の Java にないノードを導入したら、 それを標準の Java のノードに変換する「マクロ展開オブジェクト」のクラスを 定義しなければなりません。 また、定義したマクロ展開オブジェクトは、 Epp のメソッド "defineMacro" を 使って、マクロ展開オブジェクトのテーブルに登録しなければなりません。 例えば、 enum plug-in のソースコードでは、 次のようにして :enum という tag を持つ tree を展開する展開オブジェクトを登録しています。 (クラス EnumMacro は、クラス Macro のサブクラスです。)

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

マクロ展開オブジェクトは、クラス Macro のサブクラスのインスタンスです。 マクロ展開オブジェクトは、 tree を引数にとり tree を返す call という名の メソッドを持ちます。

マクロ展開オブジェクトは、 decorator pattern によって 拡張することができます。 それには、 Epp の extendMacro メソッドを使います。 decorator からは、インスタンス変数 orig を通して、 オリジナルのマクロ展開オブジェクトを呼び出すことができます。 extendMacro によって拡張されていない時は、変数 orig の値は null です。

Tree の再帰的なマクロ展開は、メソッド macroExpandTree によって行なわれます。 メソッド macroExpandTree の動作は、厳密には次のように定義されます。

      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;
すなわち、 tree の tag に対応するマクロ展開オブジェクトの メソッド call を呼び出し、返値の tag と、呼び出す前の tag が 等しければ、ループを抜けて返値を返します。そうでなければ、 tag が変わらなくなるまでマクロ展開を変換を繰り返します。 ノードの tag に対応するマクロ展開関数がない場合は、 デフォルトの動作として、自分自身の subtree をマクロ展開したものに置き換えた ノードを作ってそれを返します。

メソッド呼び出しと同じ文法を持つマクロの定義を容易にするための InvokeStyleMacro というクラスも用意されています。

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

Constructor Index

 o Macro()

Method Index

 o addTree(Symbol, Tree)
動的変数に、 tree を追加するメソッドです。.
 o call(Tree)
サブクラスにおいて、 tree をマクロ展開するメソッドを定義します。
 o checkArgsLength(Tree, int)
ノードの引数の数をチェックします。.
 o error(String)
マクロ展開時のエラーが起きた時に、呼ぶメソッドです。.
 o genTemp(String)
マクロ展開時に、ユニークな識別子を生成するために呼び出すメソッドです。.
 o macroExpand1(Tree)
マクロを1度だけ展開します。.
 o macroExpandArray(Tree[])
引数の配列の各要素をマクロ展開し、結果を新しい配列に入れて返します。
 o macroExpandTree(Tree)
再帰的に全てのマクロ展開を行なうメソッドです。.

Constructors

 o Macro
 public Macro()

Methods

 o call
 public abstract Tree call(Tree tree)
サブクラスにおいて、 tree をマクロ展開するメソッドを定義します。

 o macroExpandTree
 public static Tree macroExpandTree(Tree tree)
再帰的に全てのマクロ展開を行なうメソッドです。. 引数の tree の tag を key にして、 Macro.macroTable に登録されているマクロ展開オブジェクトを取り出し、 もしあればそれを呼び出し、なければデフォルトのマクロ展開動作を 行ないます。

plug-in プログラマーが定義する マクロ展開オブジェクトの中から、 このメソッドを明示的に呼び出しても構いませんが、 ほとんどの場合、その必要はありません。 (マクロ展開オブジェクトのメソッド call が返す tree は、 自動的に内部にマクロがなくなるまで展開される仕掛けに なっています。)

 o macroExpand1
 public static Tree macroExpand1(Tree tree)
マクロを1度だけ展開します。. 引数の tree の tag に対応するマクロ展開オブジェクトを呼び出し、 結果を返します。 マクロ展開オブジェクトのデバッグ時に、動作確認する時などに 使います。

 o macroExpandArray
 public static Tree[] macroExpandArray(Tree args[])
引数の配列の各要素をマクロ展開し、結果を新しい配列に入れて返します。

 o checkArgsLength
 public static void checkArgsLength(Tree tree,
                                    int argc)
ノードの引数の数をチェックします。. tree の args の長さが、 argc でなければ、メソッド error を呼び出します。

 o addTree
 public static void addTree(Symbol sym,
                            Tree tree)
動的変数に、 tree を追加するメソッドです。. このメソッドは、次のように定義されています。
  public static void addTree(Symbol sym, Tree tree){
    TreeVec tvec = (TreeVec)Dynamic.get(sym);
    tvec.add(macroExpandTree(tree));
  }

例えばある拡張構文をマクロ展開する際、 あるメソッドを現在展開中のクラスに追加したくなる場合があります。 そのような場合は、例えば次のようにします。

    addTree(:beginningOfClassBody,
    	    aMethodDeclarationTree);
addTree の第一引数に指定できる symbol には、現在以下のものがあります。
	:beforeCurrentTypeDeclaration
	:afterCurrentTypeDeclaration
	:beginningOfClassBody
	:beforeCurrentClassBodyDeclaration
	:afterCurrentClassBodyDeclaration
	:beforeCurrentBlockStatement
	:afterCurrentBlockStatement
これらによって、現在のファイルのトップレベルへのコードの追加、 現在のクラスへのインスタンス変数やメソッドの追加、 現在の文の直前へのローカル型宣言の追加、 現在の文の直後への後処理の追加などができます。

See Also:
Dynamic
 o genTemp
 public static Symbol genTemp(String prefix)
マクロ展開時に、ユニークな識別子を生成するために呼び出すメソッドです。. 次のように定義されています。
  public static Symbol genTemp(String prefix){
    return Symbol.intern(prefix + genTempCounter++);
  }

ここで、 genTempCounter は static 変数で、初期値は0です。 初期化は、 EPP の起動時に1度だけ行なわれます。

 o error
 public static Error error(String str)
マクロ展開時のエラーが起きた時に、呼ぶメソッドです。. クラス EppUserError のインスタンスを返します。 使い方は、 EppCore#error と同じです。

See Also:
error

All Packages  Class Hierarchy  This Package  Previous  Next  Index