Let's start Scheme

2012-12-01

Andre van Tonderの展開器を読む

やっぱりマクロ周りの問題は割りと大きくのしかかってくる感じなので、まじめに戦略を練るために既存の展開器を理解しようかなぁと思い読み始める。

とりあえず以下が理解したこと;
  • マクロ展開時にユニークなマークを作成
    • colorとなっているもの
    • これによってbound-identifier=?を実装している
  • 展開フェーズはdefine-syntaxが現れると+1される
    • Sagittariusは暗黙に解決する方向をとるので、これは要らない
  • syntax-caseのマッチはランタイムに生成される
    • パフォーマンス的にはうれしくないよなぁ
    • ただ、その分いろいろな情報解析で手を抜けそう
  • 式が渡された段階で全てのシンボルが識別子に変換されている
    • 重要だけど、リテラルなリストとかどうしようかな・・・
  • 環境は全ての束縛を保持する
    • 局所変数から大域変数、はたまた構文まで全部
    • free-identifier=?の実装には必要
      • 僕の考え方は間違ってなかったのかと納得
  • パターン変数を識別するものがある
っで、現状のSagittariusの実装とは大きく異なる部分;
  • パターンマッチは組み込みである
    • コンパイルが2度走る必要がないの多少高速なはず
  • テンプレート展開部分も組み込みである
    •  Andre van Tonderの方はこいつもマクロごとに生成される
  • ラップする式は束縛されている変数のみかつ、コンパイラが行う
    • しかも、複数回走る
    • 全体を1回だけにした方がいいが、リテラルリストをどうするか
ある意味当たり前なんだけど、マクロ展開の部分だけに目を向けるなら、syntax-caseとsyntaxだけが解決されている。つまり、それ以外のR6RSが提供する低レベルマクロ用何かしらは、すべてこの2つの組み合わせのみで解決できる。
ということは、この2つが完璧に動作さえすれば、他の動作は保障されているわけで、現状いろいろごにょごにょやっている部分がすっきりする可能性が高い。

Andre van Tonderの展開器ではポータビリティのために生成されるGUIDはシンボルなのだが、gensymがある処理系ならばこれはgensymに単純に置き換えることができる(検証もした)。ついでに、GUIDは一時変数とか、ユニークなシンボルの生成以外には使われていない。
ライブラリの関係(だけじゃないかも)で、グローバルもしくはローカルに束縛されたシンボルの実態はGUIDに変換されている。ただ、ルックアップ自体は識別子で行うので、Sagittariusではやる必要はないと思う。

全体を1回だけラップすることで起きえる問題を考えてみる;
  • リテラルリストが壊れる
    • 完全にリテラルだと分かっているならラップしないということも可能
    • quasiquoteが困りそうだがどうする?
      • ラップ時にquasiquoteだけ特別視?
    • ベクタもリテラルであるよな?
  • libraryやdefine-library構文に手を入れる必要がある。
    • exportやimportがシンボルを期待しているが、識別子になってしまう
      • まぁ、大きな問題ではない
リテラルリストだけなんとかすれば大きく問題はないと思う。ずっと使わずあるだけだったpass0手続きがついに使われるときが来たか。
気になるのは、ただでさえメモリ喰いなのにさらにメモリを喰うようになることか。読んだS式全部トラバースして、丸コピーしないといけなくなるから。まぁ、現状も似たようなことやってるし、考えるだけ無駄か。

No comments:

Post a Comment