週刊mosh - 0.2.8予報 / Makefileパーサ / profile不調とGCオーバヘッド

うーむ 短いペースで0.2.8をスケジュールしちゃうかも。。
今週はちょっと多忙につきmosh-currentを更新できていません。

fixされたIssue

0.2.8予報

次のバージョンはまだ具体的な時期をスケジュールする時期では無いんですが:

現在のドキュメンテーションはNaturalDocsを使っているんですが、個人的にソース交ぜ書きのドキュメンテーションはあまり好みでないのと、REPL中から引けるようにする準備として。
もっとも、ソース内のアノテーションも引き続きサポートする予定です。

  • nmosh/yuni関連APIの公開(process, async-io, PEG, SSAX, ...)

0.2.8の重要な機能追加は非同期I/Oになると思います。現状ではWin32(IOCP)のみ、もしかしたらkqueue(MacOS X/FreeBSD/NetBSD)が入るかも。LinuxCygwinはpollで対応する可能性有り。
非同期I/Oは初めてのnmoshでしか使えない&mosh concurrentと互換性が無いメジャーな機能になります。このへんはちょっと混乱を生みそうなのでどう出すかは考え中。

  • テスト関連のSRFIの整理

現状、mosh上のテスト手法は(mosh test)とSRFI-64等があって統一されていないので、これらを(mosh test)に統合する予定です。(mosh test)はSRFI-64やSRFI-78のスーパーセットになります。
CIとの統合を狙っています。
まだまだ設計/製作中なので不明なものとしては :

  • yuniのレコード構文(let-with, define*, make, touch, ...)

yuni(僕が以前作っていた静的型なScheme)の構文を一部導入。地味に便利です。
型(レコード型)の定義は:

(define* point (x y))

型を受け取る手続きの定義は:

(define* (proc (p point)) (let-with p (x) (display x)))

要するに、define*には全然違う2通りの意味があります。。紛らわしいけど、これらの構文は直交しているのでOKかな。と。
特徴的な機能としては、"type as name"が有ります。仮引数名を型名と一致させる糖衣構文。

(define* (proc (point)) (let-with point (x) (display x)))

procの中ではpointは単に変数になります。
レコードのインスタンスを作るにはmake、値を変えるにはtouch!

(define p (make point (x 10) (y 20))
(touch! p (y 30)) ;; yを30に設定

touch!はset!と違って常に元のインスタンスを返します。レコードは手続きの戻り値となるケースが多いので、手続きの末尾でtouch!を使えばOKにするため。
SRFI-9やR7RS(Scheme 2011) recordとは互換になる予定。R6RS recordとは互換性が有りません。
define*で指定した型は、一致しない場合即エラーになります。将来的には、コンパイル時に型のエラーを検出してしまう予定なので、この手のエラーをcatchすることは出来ません。。ただし、let-withのようなレコードのアクセサは型チェックをせず、単純にduck typingでアクセスできます。

  • パケット解析/構成構文(define-packet-type)

いわゆるGaucheperlのpack/unpackに相当するけどもっと関数的なフレームワークを準備しています。これは僕の卒論/修論を元にしていて、個人的にはmoshの重要なkiller featureとして期待している戦略的な部分です。。
平たく言うと、checksumやlengthフィールド等を自動で埋める/検証する賢いpack/unpackです。
過去にshibuya.lispのLTで発表したんですが、なかなかmosh本体にうまいこと統合できずに今に至る。( http://d.hatena.ne.jp/mjt/20090228/p1 )
今回は全体的にsyntax-rulesで実現すべく色々と黒魔術を盛り込もうとしています。
define-packet-typeで作ったpacket型は、yuniのレコード構文でアクセスします。

Makefileパーサ

まだpushできてないんですが、GaucheのPEGでMakefileのパーサを書いています。今のところ"CMakeが出力したMakefileのパース"に特化して実装中。
nmoshは将来的にclangを統合しようと目論んでいる(= mosh単体でMinGWディストリビューションとして成立させる)ので、nmosh経由で一般的なC++プロジェクトをビルドできるようにする計画です。clangの機能を認識できるMakeを作れば、本来clangのLTO機能を活用できないC++プロジェクトでも、make側で適当にオプションとリンク順を操作することでどうにかなるので。。
あと、Windows上ではclangのコンパイラドライバに頼らず、直接clangのフロントエンドを呼び出すので、それなりに高速化する はず。
clangを統合する最大の目的は、Schemeコードを静的コンパイルするため。もちろんLLVMの中間コードを直接吐いてもいいのだけど、C言語を出力するほうがずっと容易で使い回しも効くので。。

話題: profile不調とGCオーバヘッド

MLの話題はprofileの不調とGCオーバヘッド。
Petite Chezの倍くらいなら遅くても良いと思ってるけど。。(そのようなスクリプトでは、経験上ほぼBoehmGCのオーバヘッドで差がついているので。。)
個人的には、perlのような高速性も重要だと思っている。もっともnmoshはそのような意味でも遅いが。。
moshは非常に巨大(100k〜)なcode vectorを普通のGCヒープに置くので、普通のSchemeよりもずっとGC負荷が高い。特にマクロの展開後のコードが超巨大になるnmoshではこの傾向が顕著に出るので、nmoshのexpanderや基本ライブラリはmoshVMを使わないようにできないか検討している。