週刊nmosh - R7RS / フロントエンド

R7RSには賛成票。多くのケースでR6RSと相互運用できるのでこれといって大きな問題は無いかな。と。

R7RS WG2はSRFIベースに

WG2はSRFIの手続きを使って標準ライブラリを決めていくように方針転換したようだ。じゃぁ単純にSRFIの集合にすればいいような気がするけど。。
他にも、基本無期限になりメンバやSteering committeeの気が向いた時に解散するなどの微妙な調整がされた。

フロントエンド

R7RSに対応するにあたり、普通の(静的)コンパイラに近いフロントエンド / バックエンド構成の実装形態に変えていこうかと考えている。動的言語たるScheme/Lisp精神には反する気もするけど、実行前に可能な限りエラーを出しておきたい需要はどうしても有る。
いわゆるC++コンパイラ程度の機能性を実現しようと思うと:

エディタ上からのcompletionを行うためには、ソースコードが不完全でも読み取れないといけない。つまり普通のreadではなくソースコード読み取り用のpermissiveなreadが必要になる。どちらにせよ、シンボルなどの定義位置を記録したりする必要が有るので、専用readerを持つのは必要になってしまう気がする。
文字列やコメント、カッコがopenのままで終端に到達した時に、必要な閉じカッコや閉じコメントを自動で補うくらいで十分だろうか。。

  • エラーコードを使用し、エラーメッセージの国際化に配慮する

MS製のコンパイラはそれなりに一貫したエラーコードを表示する。つまり、コンパイラが表示する可能性のあるエラーの個々に番号を振り、対処方法を書いている。http://msdn.microsoft.com/ja-jp/library/x6y12zws%28v=vs.100%29.aspx
同じ事を実現するためには、reader、expander、バイトコードコンパイラのそれぞれで発生する可能性のあるエラーを全て列挙することになる。

nmoshはマクロの展開トレースを持っているので、syntax-errorに到達するまでのマクロ展開を1ステップづつ表示できる。これ自体はとても便利でC++コンパイラにも欲しいくらいだけど、それでデバッグできるのはコードを書いた本人とScheme guruだけなのでどうにかしないといけない。
↑の例だと、nmoshの拡張構文define*に異常な構文を与えても、ユーザにはletのエラーにしか見えない。define*をdefine-syntaxするときに、ちゃんと異常な構文を弾くようにsyntax-rulesを書かないといけない。。そもそもsyntax-rulesでは、その位置に書かれたものが文字列かシンボルかどうかすら展開時に判定できないので、この手のサポートをするための低レベルマクロを実装する必要がある。

これが地味に難しい。マクロが式を受け入れなかった時に単純にその式を飛ばすことが出来るのかが謎。未知の識別子を発見したときに、一旦undefinedにbindして処理を継続する必要がある。
いわゆるdid you mean?が出せると良いが、その候補を適当に選択して良いものかどうかが絶妙。