修論を書こう

もうプロシンの季節なのか。。それまでにyuniSchemeは公開したかったけど延期ということで(今年度中には)。。今は純粋なR6RSライブラリとしての比重を増やす方向で検討していて、最適化コンパイラは後回しにしつつ。
でもマクロを駆使して既存のSchemeの上に載せると非常にコンパクトになってしまうので、2年間の大学院生活はなんだったんだという気持ちにも。要するにコンパイラの方向であんまり成果が出なかったのが不味いところ。
技術的な要素は以下の3つ。

構造体の可読化

可読化といってもkeylistと呼ぶ、キーワードと値のペアのリストにするだけ。例えば、SCSIのコマンドが

(READ/10 :LBA 990 :Transfer-length 512)

のようなリストになるだけ*1。これをSchemeで操作しろという課題は非常に簡単なので、そういうライブラリが世間一般のプロトコルに提供されているだけでも欲しいという人は多いはずはず。。
ポイントは、通常の人間に要らないフィールド(チェックサムなど)は自動的に省略すること。future workは、この省略を制御するためのうまい方法を考えること。。(テストのために異常なチェックサムのパケットを作りたいひとも居るので)
キーワードをネイティブにサポートしていると、インタプリタ側でもうまく最適化する余地があるので美味いけれど、ちょっと大変そうなので保留。そのかわり、keylistに対するlet(let-keywords)や、それをrecordから構築する手続き(record→bytevector)の類を提供することに。

pack/unpackコードの自動生成

yuniSchemeは上のようなリストを、いわゆる構造体やバイト列に押し込めたり、逆にバイト列を上のようなリストに変換する手続きを自動的に生成してくれる。
...当初の計画から一番縮退したのはここで、本来はここに対する最適化コンパイラを作ることで既存の(人間が手書きした)pack/unpackよりも高速になることを目指していた。この領域は(ビット操作命令のような)CPUの機能を駆使すると早いけどC言語では書きづらいというニッチなので。で、2年研究したけど成果が出なかった(10GbEとかでない限りはI/Oのほうがずっと遅かったため。ファイル形式のパースやデータ構造の操作ならまだ可能性があるが)。
ポイントは、可変長のデータ構造もちゃんとhandleし、どの順序でデータを必要とするかもトポロジカルソートでどうにか見つけてくれる点。まぁ通常のプロトコルは先頭からパケットを構築していけば上手く行くように出来てるんですが。future workは先述のコンパイラと、プロトコルの検証のための機能。曖昧なプロトコルを設計してしまった場合、このコード生成のタイミングで曖昧だとわかるので、それを通知するようなインターフェース。

プロトコル記述言語

これらを"一般のプロトコルに対して提供する"ためには、それなりの記述能力を持って、かつ簡単に記述できるプロトコル記述言語が要る。
この辺は主観が入るので何とも言えない。

(define-packet-format op/READ-10
   (LUN u3)
   (DPO flag)
   (FUA flag)
   (Reserved u2)
   (RelAdr flag)
   (LBA u32)
   (Reserved u8)
   (Transfer-length u16)
   (Control u8))

のような、packet format宣言を書けば、あとのAPI生成などはシステムが面倒を見る。
プロシンではreadとwriteだけにしろみたいな過激な主張だったけど、IDEが支援できるだろうから、機械的に生成できるAPIならアリかなと考えを転換しつつ。。
該当するRFC番号とか、USBのVID+PIDのようなメタデータも持たせられるようにしている。
ここ暫くは、このプロトコル記述言語がR6RSのライブラリとしても正当になるように検討していたが、残念ながらそれは無理そうなので、簡単な(S式をちょっと変換するだけの)コンパイラを用意して、それを通してから使って貰う形になる。nmoshは直接読む機能をつける予定なので、デバイス制御やファイル形式方面で盤石なシェアを将来は確保したい。
TCPやUSBのような通信プロトコルは書けるが、まだファイル形式に関しては上手いサポートが無いのが現状。ファイルシステムやDBが表現できる程度が目標でfuture work。
この言語で書かれたプロトコルを集めるWikiを作るつもりだったけど、githubで同じことが出来ると考え直した。
HTTPのようなテキストベースのプロトコルはサポートしていない。一般に、人間に親切というのは機械に不親切なので。

*1:LBAはLogical Block Addressで、操作対象のアドレスを表す。