マクロの実装を想像する
目的と経緯
マクロを実装するにあたり、マクロをある程度知ることはできた。
次はマクロを実装する裏側を想像し、それが妥当かどうか検証する。
お題
まず考えるためのお題は
(define-syntax when (syntax-rules () ((_ pred a b) (if pred (begin a b)))))
としよう。
2つのフェーズ
インタプリタから見ると大きく2つのフェーズがあるように見える
- define-syntax を与えられて解釈して、あれこれするフェーズ
- define-syntax で define されたマクロが別の文脈で呼び出されたときにコードを生成するフェーズ
define-syntax を与えられて解釈して、あれこれするフェーズ
when というキーワードに対して2つのものを解釈し保持する
- when の書き方ルール
- ルールを展開結果
現時点では、まだ理解が浅いので何とも言えないが、when を置き換えルールで別のソースコードに変換するイメージか。
でも、Cのマクロとは違うとどこかで読んだので単純に置き換えモデルのではないのかも。
ふと
C++のテンプレートをうまく活用できないだろうかと考える。
マッチした場合
Nodeツリーの位置で書かれた変換表に従いソースコード変換。
その後 eval 。
テスト期
いろいろ考えていたら、まずはテストだと思いつく。
テスト期テスト期。
cppunitを使ってこんな感じで。
#define MACRO_MATCH(macroName, macro, target, matchOrNot) \ { \ Node* m = Macro::toNode(macro); \ Node* t = Macro::toNode(target); \ CPPUNIT_ASSERT_MESSAGE(matchOrNot ? macro " matches " target : macro " not match " target \ , Macro::match(macroName, m, t) == matchOrNot); \ } #define _Y(macroName, macro, target) MACRO_MATCH(macroName, macro, target, true) #define _N(macroName, macro, target) MACRO_MATCH(macroName, macro, target, false) void MacroMatchTest::testNormalMatch() { _Y("and", "(_ a b ...)", "(and a b c)"); _N("and", "(_ a)" , "(and a b)"); }
よしテストの準備は出来た。
match関数は誰か書いて(ぉ。