220 likes | 327 Views
EPP: E xtensive Java P re p rocessor. Survey: Yutaka Oiwa Jul 10, 2000. What’s EPP?. 一杉氏 @電総研 作の Java 用 Preprocessor 文法解析ルーチンの拡張が簡単に可能 Mix-in モデルに基づく拡張の組み合わせ 型情報に基づく書き換えのサポート URI : http://www.etl.go.jp/etl/divisions/~epp/. EPP の用途. Java 言語の拡張用 preprocessor Java のソースコードの解析ツール
E N D
EPP: Extensive Java Preprocessor Survey: Yutaka Oiwa Jul 10, 2000
What’s EPP? • 一杉氏@電総研 作の Java 用 Preprocessor • 文法解析ルーチンの拡張が簡単に可能 • Mix-in モデルに基づく拡張の組み合わせ • 型情報に基づく書き換えのサポート URI : http://www.etl.go.jp/etl/divisions/~epp/
EPP の用途 • Java 言語の拡張用 preprocessor • Java のソースコードの解析ツール • Java のソース→ソース変換ツール ... を作るためのツールキット
EPP でできる書き換え • Java(+α) → Java のソース→ソース変換ならほとんど全て • 例えば... • 簡単なもの: enum, symbol, typeof, #ifdef, etc... • 中程度なもの: 連想配列 etc... • 大規模なもの: • SystemMixin (EPP の mix-in 機構) • Tiny DataPallel Java (SWoPP’97)(in old EPP written on Lisp...) • JavaGo みたいなものとか...
Plugin1 Plugin2 Plugin3 EPP structure Input • 4 段階の処理フェーズ • 構文解析 • マクロ展開 • 型チェック (optional) • コード出力 • 各段階を拡張可能 • 通常は上3つをplugin で拡張する Output
Parser phase • 入力を構文解析して Abstract Syntax Tree を生成するフェーズ • Java 用の再帰下降パーサが組み込み • 各 entry (例えば primary expression) をmix-in (後述) で拡張できる
Macro Expand Phase • Parser phase で生成された AST を再帰的に変換する phase • AST 中の各要素型に対して変換処理を記述 • デフォルトはなにもしない • ほぼありとあらゆる型に依らない書き換えが書ける • 「現在のクラスに要素を追加」なども可能
Type Checking Phase • AST を再帰探索して静的な型付けを与える • ここでもローカルな式の書き換えは可能 • 型情報を用いた書き換え規則を記述できる
Code Emit Phase • ここまでで得られた Java の AST を実際のプログラムソースに変換する • ここはあまり拡張しない (らしい)
EPP のプログラミングスタイル • 解析したい文法の拡張部分の parser を独自言語 Ld-2 で差分だけ記述 • 構文木に新たな型のノードを追加 • Mix-in Program Model でフックをかける • マクロ展開フェーズか型チェックフェーズで拡張された AST を通常の AST に変換 • ノードの型でフックをかける
Mix-in Model とは? (1) • 1つのクラスを分割して記述する機構 • 例: あるクラス Foo class Foo { void m(String d) { if ( d.equals("B") ) doB(); else if ( d.equals("A") ) doA(); else { doDefault(); } } に else if (d.equals(“C”)) { doC(); } を追加したい
Mix-in Model とは? (2) • 通常の型継承の場合 class Bar extends Foo { void m (String d) { if d.equals(“C”) doC(); else super.m(d); } } • しかし、型の名前は変わってしまう! • 他所からの参照があると困ってしまう • Plugin 同士の衝突が起きやすい
Mix-in Model とは? (3) • Mix-in Model での解決: • この処理を3つの mix-in で記述 • SystemMixin Skeleton { class Foo { define void m(String d){ doDefault(); } } }
Mix-in Model とは? (4) • SystemMixin A { class Foo { extend void m(String d){ if(d.equals(“A”)) doA(); else original(); } } } • SystemMixin B { ....extend void m (...) ........}
Mix-in Model とは? (5) • Mix-in Model での解決 (続) • 実行直前にこれらの Mix-in から1つのクラスを生成 • 読み込まれた全ての Foo::m の定義を結合して1つのメソッドを構成 • 外部参照・サブクラスへメソッドの変更の影響が自動的に伝播する • Ld-2 言語の key feature
Mix-in Model とは? (6) • EPP では... • parser の拡張に Mix-in を利用 • 例: symbol plugin extend Tree primaryTop() { // Java 用の primaryTop に if (lookahead() == :“:”) { // Hook をかける return symbol(); // ←“:foo” を解釈して (:symbol foo) } else { // を返すメソッド (新設) return original(); } }
EPP plugin の例 (1) • enum plugin (リスト enum/Plugin.java) • enum { RED, BLUE, ... } →public static int RED = 0; public static INT BLUE = 1; ... • parser: クラスメンバ宣言 (classBodyDeclaration) にフック、enum { .... } を (:enum ..... ) という AST に • expander: enum が出てきたらそのクラスの定義の先頭に public static int .... を追加( addTree(:beginningOfClassBody, ....) )
EPP plugin の例 (2) • typeof Plugin (リスト typeof/Plugin.java) • (typeof(a)) b; → (int) b; • type checker: ( ) 内に与えられた式を型付けし、 その結果で全体を置き換え
EPP plugin の例 (3) • BackQuote plugin (BackQuote/PlugIn.java) • plugin 開発者用 plugin • `(S式) という式を new Tree(...) というEPP 内部の構文木データ構造に変換
EPP プログラムの開発 • 結局、EPP を使うのに必要なのは... • Java の知識 (当然) • 再帰下降パーサの理解 • 抽象構文木とは何ぞや? • 割とお気楽に preprocess できます
いまやってること... (1) • とりあえず `C の Java 版みたいなもの書いてます • EPP で preprocess • EPP マクロで cspec の構文木から直接Java バイトコード生成器を気合で生成 (第1版) → SPA ‘00 のポスターセッション • backend に javac を使う (第2版) • EPP → javac → 自作フィルタ → javac (SIGのほうでもう少し詳細を話す/話した 予定)
いまやってること...(2) • 方向性としては... • `C のような動的コード生成を Java のような object-oriented, strongly static typed の世界の実用言語に持ち込む • 動的コードに対する typing • メソッド引数とか、「文脈」を要求するコードの扱い • Object-oriented との関連 • class とかも動的に作りたい → typing は? 実現は? • もっと高級に書きたい • 「partial evaluation を explicit に書いた」くらいにはしたい やること山積