mosh近況

長い道程。。基本的には休みを潰してoniguruma対策。

google testのアップデート

google testのディストリビューション全体を含む理由は特にないので、google testをアップデートしてファイルを統合した。
ただ、最近のGoogle testはPOSIX正規表現サポートを含んでいて、これがmoshに含まれるonigurumaと衝突するという問題が有る。これはONIG_ESCAPE_REGEX_T_COLLISIONを定義したり、oniguruma.hをincludeする前にいくつかの定義を変更するなどして回避したが、FreeBSDのように"regex.hは有るけどgoogle testがそれをincludeしないプラットフォーム"では問題が起こるのでまだ対策途上。

onigurumaのunbundle

moshは長いことoniguruma(正規表現エンジン)をソースツリーに含んでいて、moshのビルド時に同時にビルドしていた。ただ、oniguruma自体は完全に独立したライブラリなので、システムに一つだけonigurumaをインストールし、一元的に管理したいという需要もある。
というわけで、gccと同様に、"ソースツリー中にonigurumaのディレクトリが有ったら同時にconfigure&ビルド、そうでなければonig-configから情報を取得"というふうに変更した。
この変更がmasterに反映されるかどうかは未定。ただ、既にonigurumaを持っているFreeBSD portsMacPortsの対応に必要なのでforkなりなんなりの形でメンテナンスする予定。

onigurumaのdisable (未遂)

本来はonigurumaのunbundleでなくて、MSVC、XCode等ではoniguruma自体を削除する方向で作業していた。これらのプラットフォームでは、そもそも、autoconfなライブラリを複数利用すること自体が難しい。
今のmoshにはpure scheme正規表現実装であるirregexも有り、これもPOSIX正規表現Unicodeに対応しているので、原理的には大抵のスクリプトで互換性を保ったままirregexにフォールバックできる。
ただ、1) moshにとって正規表現オブジェクトはfirst classなので、それを削除すると変更範囲が膨大になる 2) いくつかのライブラリが正規表現リテラルに依存している 3) 正規表現リテラルをpure schemeで実装する上手い手法が無い。
R6RS的には、readerが#!r6rsを認識していないときはいかなる独自拡張をしていても良いのだけれど、readerが導入するシンボルが(rnrs)以外に存在していて良いのかどうかというのも微妙なところ。
要するに、"#/hoge/"をreadすると"(irregex "hoge")になることが良いのかどうかという問題。現状、"'hoge"が"(quote hoge)"と読まれるのと意味合いとしては変わらないが。。

expanderの置き換え (作業中)

将来のリリースで、nmoshのexpanderを自前のもので置き換える予定。目的は :

  • REPL上でのTAB補完の実現
  • 自前のreaderを持つことでより正確なエラーメッセージを出力
  • expandされたコードの高速化

今のところ、まだまだ実装の初期段階で、0.2.6に含めるかどうかは未定。
moshにはuninternedなシンボルの概念が無いため、expanderはシンボルを直接扱わず、バックエンドに渡すまでidentifierオブジェクトのまま処理するように書いている。現状のnmoshでは、シンボルのrenameにそれなりに時間が掛っているため、規模が大きいスクリプトではexpandが多少高速になるかもしれない。
また、α変換を必要最低限しか行わないようになった。α変換自体はexpander内部で行っているが、シンボルの生成にそれなりの時間が掛かる*1ので、出力する段階で、ローカル束縛(ソースコードに記述されていて、マクロに導入されたわけでは無いシンボル)はrenameしないようにした。
R6RS実装依存としている部分の挙動はnmoshのものを基本的に受けついでいる。他の拡張は :

  • "stage"(ライブラリ環境)の概念を持つ。ライブラリのloadをstageに対して行い、システムは複数のstageを持つことができる。nmoshでも、対話環境に対して破壊的にライブラリをimportする機能が有るが、一度loadされたライブラリを変更するうまい方法は無かった。*2
    • この機能は要するに外部のコンパイラとexpanderを共有するために入れている。複数のstageを使うことで、異なるcore schemeに対して共通のライブラリをexpandできる。
    • 副産物として、伝統的なBASICのnew文に相当することがREPL上から可能になる。単にstageを作りなおすことで、一度importしたライブラリの束縛を破棄することができる。
  • ライブラリはロードされてから一度だけvisitされることが保証される。stage毎に一度なのかセッション毎に一度なのかは未定。
  • 依存関係は全てのライブラリを列挙した後に解決される。つまり、ライブラリを含むプログラムで、ライブラリを依存関係順にソートして書く必要が無くなる。

*1:シンボルの生成のためにnumber→stringするため。Chezのように、これを実際の表示時まで遅延させる実装もあるが。。

*2:束縛を上書きすることはできるが、一度loadされたライブラリはメモリに残り続ける。