nmoshとは何か

moshに移植した物。

前提

moshの一部分はmosh自身のSchemeで書かれている。たとえばキャッシュの制御とか、VM命令へのコンパイラのようなコアにまつわる物など。
このうち、R6RSのマクロとライブラリに関する部分(expander)は、従来、psyntaxと呼ばれる物(Ikarusの一部)をhigeponが移植して使っていた。
ypsilonはpsyntaxだったが自前の実装に移行した(Shibuya.lisp TT #2 http://www.youtube.com/watch?v=FPsjXt9MytI )。
moshはIkarus以外としてpsyntaxを採用しているが、psyntaxそのものがそれなりに複雑で(少なくとも僕にとって)メンテナンス性に難が有った。そこでよりシンプルな↑をmoshに移植し、ライブラリキャッシュなどの機能を追加した。これは当初SRFI-72のリファレンス実装として公開されていたもので、R6RSをフルサポートするようにそれなりに拡張されている。同じ実装はLarcenyがR6RSモードとして利用しており、他にGambit-R6RS( http://smyles.com/projects/r6gambit/ )も同様。
平たく言えば、moshそれ自身ではR5RSのサブセットと、R6RSの多くの手続きしか実行出来ない(mosh -5で起動した状態)。expanderは、R6RSスクリプトを読み取って、mosh -5で実行できるようなschemeスクリプトに変換する役割を持つ。

メリット

  • psyntaxよりシンプル
  • R5RS Schemeが有ればブートストラップ出来る
    • 今はGaucheによるブートストラップをサポートしている。moshVMにもGauche版が有るため、Gaucheさえあればgitのソースツリーからコードを生成できる。
    • psyntaxは"動くmosh"が生成に必要だったので、動くmoshが無いとソースツリーを生成できなかった。
  • マクロ展開用のライブラリを提供している。
  • ypsilonのように、loadが使える。(rnrs load)をインポートする。
  • マクロをデバッグするための機能が幾つかある。expandのトレース等。
    • 構文オブジェクトをクエリすることが出来るので、macro transformer中に呼び出しもとの行番号を表示するといったことも出来る(まだ多少不正確)。
  • ライブラリを絶対パスで扱う等、psyntax moshよりも信頼性が高い。(少なくともサイレントに失敗することは無い)

デメリット

  • (expandが)遅い。
    • psyntaxと違い、nmoshはシンボルを明示的にリネームする。Chez Schemeがやっているように、シンボルの生成を遅延させるような(面倒な)工夫をしないと、根本的には早くならないだろう。
    • (ちなみにChez Schemeもpsyntaxと同じ方針(mark & antimark)でマクロ展開を実装している。これはSRFI-93に有る)
    • ただ、個人的にはexpandの遅さは許容範囲に収まると考えている。
  • (expandされたコードが)遅い。
    • 今のところ、mosh -5がサポートしているletやletrecのようなbinding constructを利用していないので、無駄なクロージャ生成がでていると考えている。
  • 非互換性がある
    • R6RSで任意とされている点に関して幾つかの違いがある。もっとも大きな違いはLibraryのimportレベルの扱い。
    • 多分、多くのライブラリでは(for (your library) expand run)のような指定を明示する必要がある。(R6RS互換になるためには、本来このような記述が必要)
    • test your library!

tips

  • しばらくはmoshと一緒にnmoshもインストールされる。moshが従来のpsyntaxによるmoshで、nmoshがこの実装。
  • nmoshはキャッシュを~/.nmosh-cacheに作るので、上手く動かないときは消す。(これはリリースまでに解決したい。。)
  • ライブラリのキャッシュだけをしたいときはREPLでimportする。

nmoshの名前はnon-prefixed moshの略で、当初はアプリケーション組み込み用のmoshとして考えていた。もちろん、psyntax mosh(pmosh)と比べて、pMOSとnMOSの関係から連想されるようにしている。cmoshが出るかどうかは現時点では未定。