R7RSライブラリの読み取りに対応

yuniFFIをGaucheやchibiに移植するにあたって、R7RS形式のライブラリがnmoshで読めないと色々と不便(普段の開発はnmoshでやってるので)。というわけで、お手軽な方法でR7RSライブラリの読み取りに対応してみた。
従来から、R6RSライブラリからR7RS small言語の多く(includeやcond-expandを除く)を使用できたので、今回はexpander側の対応を追加した。
まだcond-expandがちゃんと実装されていない。nmoshにはcond-expandのlibraryクエリを実装する良い方法が無いので方法論を考え中。

対応手法

基本的な対応手法は、R7RSライブラリをR6RSライブラリにlowerする方法で行っている。R7RSライブラリはR6RSと違ってimportやexportは任意の順番に出現することができ、cond-expandやincludeが統合されている。一方、R7RSとしてはこれらの処理順序に関しては特に規定していないので:

  1. まず、cond-expandとincludeを上から順番に処理し、exportとimport、beginを収集する
  2. export、import、beginを収集した順にまとめて出力する

という方法でR6RSライブラリに変換し、従来のnmosh expanderで処理している。
基本的にはR6RS expanderのまま、通常のR6RSライブラリとして変換hookを書けるようにいくつかの処理を追加している。

マクロから展開中のファイルのパスを問い合わせられるようにしている。C言語等の__FILE__に相当する処理。
これは、R7RS includeの実装に必要になる。includeで指定するファイルは、通常元のライブラリソースの存在するディレクトリに置かれるため、include元ファイルのパスを取得できないとinclude先のファイル名も生成できない。
これを汎用的にマクロ内でサポートするかどうかは微妙なポイントと言える。syntax query(マクロ内からidentifierの定義行とファイル名を得る機能。公開版のnmoshには無い。)と違って、このパス取得は動かなかった場合の良いfallbackが無い。
また、replからライブラリを定義する際にincludeできない。

expanderにhookを追加し、library シンボルが表われるべきところでdefine-libraryが表われたらライブラリ(nmosh r7rs loader)を読み込み、ライブラリを変換する。
ちなみにソースコードはnmoshのannotated-pair状態で処理されるので、変換/includeによって定義位置などの情報が失われることはない。

R7RSはライブラリ名のコンポーネントとして数値を許している。今のところこれを直接nmoshでサポートする予定は無いが、srfiに関しては頻出なので組込みの変換をサポートする。
(srfi 1)は(srfi :1)のようなSRFI-97互換名に変換される。

ライブラリ拡張子としてChibi-scheme互換の".sld"を追加した。
どうもchibi-schemeの影響で、R7RSライブラリは拡張子 .sld 、bodyを分離する場合は同名の .scm が標準になりつつあるように見えるので、追従した。