ciseがR6RSにも欲しい

Gaucheにはgauche.cgen.ciseという(undocumentedで)便利なライブラリがあり、S式で書いたプログラムをC言語ソースに変換することが出来る。
これをそのままmoshに持ち込むのはちょっと大変なので、外堀を埋めていく形で少しづつ進めている。

  • (fmt)ライブラリ。これはciseとは別の記法のS式から、読めるCコードを出力する。
  • オブジェクトシステムのC言語インターフェース。
  • マクロを展開するためのライブラリ(nmosh expander)。

もちろん元がC++なんだからC++のコードを出力すればという説も有るが、C++のコードを出力しても意味がない。平たく言えば(今後普及するであろう)OpenCLコンパイラはCのコンパイラであり、C++でない。あと、C++には明確に機能するABIが無いため、実行中のランタイムを出力したコンパイラでなければ機能する追加コードを出力できない。(一般には、この問題に対処するためにCOMとかXPCOMのような手法が利用されてきたが、個人的な観点から言うとこれらには未来が無い。これは言語処理系をC++で書くべきではない重要な理由の一つ。)
単純に興味が有るのは、R6RSのライブラリシステムで実装できるかどうか。つまり、

(library (some library)
  (export compiled-function)
  (import (c compatible words)
          (only (rnrs base) define lambda define-syntax syntax-rules))
(define-syntax ...

のように、cise的に互換する(= C言語インターフェースを装備している)語彙と、R6RSのマクロシステムを混合して記述できるかどうか。
C言語ソースを出力するケースでは、expand時にはScheme側のオブジェクトシステムが使用でき、run時には使えないことになる。
今回移植したexpanderは、フェーズ毎の単語の有効性を確認する。つまり、マクロ展開時に使える語彙と、実行時に使える語彙を明確に区別することができる(psyntaxはこれが出来ない)。
結論としては、本来R6RSのライブラリシステムはこのようなケースを処理できない。これらはライブラリの語彙のみに着目していて、expand時に生成したオブジェクトはrun時にも使えることが前提になっている。
しかし、マクロの使用法によっては実行時にSchemeオブジェクトが残らないケースも考えられる。例えば展開時に生成したオブジェクトに対してdatum→syntaxを行うようなケースが該当する。

Gaucheのケース

Gaucheの場合は、ifや他のキーワードに関してexpanderを別途設けて対応している。

平たく言えばcise.scm自身がちょっとしたScheme実装に相当し、環境などの管理も行うことになる。
マクロ以外のオペレーションには全て別名を付けている。つまり、list等の操作は常にSCM_*やScm_*に展開されることになる。GaucheはC側のマクロと関数を区別する必要はない。

課題のまとめ

  • Gaucheは、ifやdotimesのようなマクロ定義を展開器(cise.scm)側に持っている。
  • R6RSの機能をうまくつかうことで、R6RSのマクロ定義を流用しつつciseのような機能を実現できるのではないだろうか。
    • cise用のSRFI-42を書かなくても、既存のSRFI-42実装を流用できないだろうかetc..
  • そのためには、少なくとも展開されたCソースからmosh側のオブジェクトシステムを操作するための方法論が必要になる。