syntax-rules実装への道

そろそろ自前のsyntax-rules実装を持った方が良いんじゃないかということで検討をしている。というのは、Google codeのSVNホスティングがそのうち終わってしまう都合でpsyntaxのbootstrapを自前で行う必要があるため。

方針

大きな方針としては:

  1. yuni上に実装する(R7RS/R6RSであれば他所のSchemeでも動作するようにする)
  2. R6RSライブラリ構文をサポートする - R7RS/cond-expandは後回し
  3. パターン/テンプレートのインタプリタとして動作する
  4. シンボル行:カラム位置のトラッキング(Vectorを含む) - 対応readerは後回し
  5. 現代的なエラーメッセージの出力とinspection
  6. 無駄なシンボルのinternを避ける

最低でも現状のnmoshと同レベルのmacro tracingをサポートしたい。
... syntax-rules実装にこんなに力を入れる意味が有るのかというのは非常に難しい問題だが、syntax-rulesの次は一般 S式/XML matcherやsyntax-case実装への応用を考えている。

各種処理系のsyntax-rules/syntax-case実装

設計に入る前に他所のScheme処理系を見て廻る。傾向としては3通りある:

  1. Syntax-rules構文上のインタプリタとして動作する(EIOD/Alexpander)
  2. パタン変数へのバインディングを作成するコードと、テンプレートの展開を行うコードにマクロ展開される(nmosh/psyntax/Chicken/...)
  3. パタン/テンプレートオブジェクトへ一旦コンパイルし、それを解釈する(Gauche)

個々の実装は:

  • EIOD

EIODの実装( https://github.com/okuoku/eiod-r6rs/blob/master/eiod.scm#L225 )はギリギリ100行に収まっている。パタンのlengthはマッチの度に導出しているなど幾つかのポイントで単純化をしている。

  • Alexpander

EIODと同じ作者によるAlexpanderは、構文のverifcationである`compile-syntax-rules`( https://github.com/okuoku/mosh/blob/c632378031e16fd3fa059087a30ba04055c54656/boot/runtimes/srfi-mosh/bootstrap.common/alexpander.scm#L1135 )と、パタンの解釈とテンプレート展開を行う`apply-transformer`に分割されている。
compile-syntax-rulesにはありえそうなエラーが列挙されている。R6RS/R7RSでは追加の制約や緩和があるが、参考になる。

  • nmosh / psyntax-mosh

nmoshのexpanderはSRFI-72参照実装( http://www.het.brown.edu/people/andre/macros/index.htm )をほぼそのまま使用していて、macroの展開を全部traceできるという特徴がある。他にはLarcenyがR6RSのためにこれを使用している。
nmoshの場合、パタン変数へのバインディングを作成するコードに展開される`process-clauses`( https://github.com/okuoku/mosh/blob/c632378031e16fd3fa059087a30ba04055c54656/boot/runtimes/srfi-mosh/expander.scm#L1464 )と、syntax構文によって実際のパタン変数の展開を行うコードに展開される`process-template`に別れている。`ex:map-while`のようなランタイム関数がグローバルに束縛されていることを前提にしている。
psyntax-moshは名前の通りpsyntaxそのもの。`syntax-case-transformer`( https://github.com/okuoku/mosh/blob/c632378031e16fd3fa059087a30ba04055c54656/boot/runtimes/psyntax-mosh/psyntax/expander.ss#L2475 )と`syntax-transformer`に別れている。psyntaxのmatcher(`syntax-match`)はsyntax-caseで書かれている。
nmoshとpsyntax-moshいづれも、matcherのコードはSchemeコードに展開される。

Gaucheのsyntax-rules実装はなんとC側に存在する( https://github.com/shirok/Gauche/blob/fef1cc7babb8c60008aa4ab00859092c89a6edb7/src/macro.c )。er-macro-transformerの実装がcompiler.scm側に追加されたので、そちらに移行できるかもしれない。

  • Chicken / riaxpander

ChickenはTRCのriaxpanderに移植されたsyntax-rules実装( https://github.com/matthastie/riaxpander/blob/master/synrules.scm )をさらに移植して( http://code.call-cc.org/cgi-bin/gitweb.cgi?p=chicken-core.git;a=blob;f=synrules.scm;h=cf8912ec0d568de55ef02b14b6b8d8661fc840b9;hb=98deea7246a10b37939eeb89aa98b1e3a7a0c413 )使用している。オーソドックスなer-macro-transformer上の実装。

Chibi-schemeもオーソドックスなer-macro-transformer上の実装( https://github.com/ashinn/chibi-scheme/blob/7f1786f85443d21252c92867137df81713e59209/lib/init-7.scm#L672 )。

次の一手

構成を考える。たぶん、良いdiagnosisやコード補完のサポートを行うためには、

  1. パタンとテンプレートを一旦中間表現に変換する(この時点でエラー検出も行う)
  2. 変換した中間表現上で動作するインタプリタとして実装する

のが良い気がしている。このため、次の一手としては適当な中間表現を設計する必要がある。