R6RS Macros and R6RS librariesを今度こそ移植する の2

多少長いコードも正常に走るようになってきた。moshのライブラリはインポートレベルに問題があるものが少なからずあるようなので、これをつかって修正できる。

多重defineの許可

moshは元のVMレベルで多重defineを不許可にしている。要するに、mosh -5の状態でも、

(define a 10)
(define a 20)
(display a)

のようなコードは走らない。今のところmoshには値がimmutableかどうかに依存する最適化は無いのでVM-Run.cppにパッチして許可してしまった。
R6RS Macros and R6RS librariesは、コードをR5RS かつ マクロを使用しないコードに展開する*1ので、同じようにコンパイルしたライブラリを複数回ロードすると、同じシンボルへのdefineが発生することになる。

Larcenyからの輸入

同じくR6RS Macros and R6RS librariesをベースとしたR6RS実装を持つので、幾つかの定義はLarcenyから輸入している。
LarcenyはBSD-likeのライセンスで、BSD同様に著作権表示さえしていけば部分的な再配布ができる。

Gaucheによる展開

GaucheR6RS準拠のリーダを備えていないので、R6RSスクリプトに含まれる多くの#表記をパースすることが出来ない。
元の記述にはそのような表記は殆ど含まれていないないが、syntaxやunsyntaxが多くあるので、一旦moshでreadしてwriteしてからGaucheに展開させている。
Gaucheの出力もR6RSでは無いが、いわゆる...のような外部表現の異なるものだけを(通常のmoshのビルドプロセス同様)sedで変換している。

足りないライブラリ

多くのライブラリが高速に揃ったのは、単にmoshの内蔵ライブラリさえ呼び出せばOKという仕組みになっているため。R6RS Macros and R6RS librariesはライブラリ記述を拡張しており、ライブラリとしてprimitivesを指定すると内蔵シンボルを呼び出せるようになっている。例えば、moshの内蔵シンボルは以下のように、単にprimitivesからインポートしてエクスポートするだけになる。

(library (mosh) ; mosh internal library
  (export current-directory mosh-executable-path standard-library-path command-line os-constant)
  (import
    (primitives current-directory mosh-executable-path standard-library-path
                command-line os-constant)))

しかし、単純に、マクロ(構文)はifのような例外を除くと元の実装から持ってくることは出来ない。幸い、psyntaxと異なり、R6RS Macros and R6RS librariesでは基盤ライブラリもsyntax-caseやsyntax-rulesを使って記述することが出来るので、問題は多少簡単になる。単に、R6RSを使ってこれらのライブラリを実装すれば良い。
今のところ欠落している重要なライブラリはrecords syntactic関連で、conditionsもこれに依存している。
個人的には可能な限り多くをSchemeで書くべきだと思っているので、"R6RSで書かれたR6RS"として実装を整理するのはそれなりに意味があると考えられる。

*1:これらはletrecなどの展開も含むので、結果として静的なコンパイラには有利なコードが出てくる。逆にVM型のシステムでは単に非効率だろう。