静的型システム
mosh 0.2.7に入れようとしているライブラリ(LLVM bitcode readerやELF/DWARF4パーサ)はyuni由来の簡易型システムに依存している。
yuniは、元々パケットフォーマットを静的型と見做すという絶妙に特殊な用途のために設計された言語なので、RubyのオブジェクトシステムやCLOSのようなシステムに比べるとあまりにもシンプルで機能が少ない。
さらに、現状の実装は純粋にSchemeで書かれているので遅いという問題が有る。LLVM bitcode readerの場合、型チェックを省くだけで2倍ちかく高速になり、それでも通常の利用用途に使うには遅すぎる。
というわけで:
ことの両方が要求されている。
実装方針
実装の方針はいくつか考えられる。
まず、現状のmoshは、ユーザ側がSchemeシステム上のオブジェクトクラスを拡張できるようにはデザインされていない。
このため、現状のyuni coreでは、simple-struct(vector?を満たさないvector)で全てのオブジェクトを表現している。
このmoshのオブジェクトシステムには手を入れず、simple-structを使い続けて高速化するには、expanderかVMコンパイラのどちらかに、静的型のアノテーションを導入する必要がある。
メリット: ライブラリをexpandするときだけ時間を掛けて最適化し、通常の実行では従来通りランタイムで型を解決するといった柔軟な実装が行える。また、実装が比較的容易。
GaucheのようにVMレベルでのディスパッチをサポートするという方向性も考えられる。
Gaucheはタグの下位が111bであるようなオブジェクトをClassを持ったオブジェクトと定義していて、VMレベルでClassの解決をサポートしている。
Moshでも同様のサポートを行うことが考えられる。
メリット: CLOS風の動的なオブジェクトシステムを導入するといった拡張性を持たせられる。
今のところは前者の方針が有力で、特に実装を静的コンパイラでも流用できる*1点はポイントになる。
追加すべき機能
現代的な(?)プログラミングのために、いくつかの機能を追加したい。
- メソッド
現在、yuniの静的型を使った関数はdefine*で定義することができる。つまり、型TCPHeaderが存在する*2として、
(define* (get-checksum (packet TCPHeader)) ;; 処理 )
のようにget-checksum手続きを定義することができる(yuniでは型を後ろに書く)。このようにして定義されたget-checksumはTCPHeader以外のオブジェクトを渡すとエラーになる。
これを単純に拡張して、別のシグネチャを持つdefine*を多重に定義できるようにすることも考えられる。が、これはR6RSの前提である"ライブラリ経由で導入したシンボルはimmutable"という特徴を否定することになってしまう。。
今考えているのは、C++風に、型のメンバとしてメソッドも含めるという方針で、この場合はメソッドの呼び出し構文が問題になる。
もちろん、
(get-checksum packet)
のように、(メソッド名 オブジェクト)の自然な構文でメソッドを起動できるのが望ましいが、これは(多分)R6RSで実装できないという問題が有る。
yuniはGauche風のgenericなref構文を持っているので、
((~ packet 'get-checksum) packet)
と書けば呼ぶことはできるがカッコ悪い。。専用構文を用意して、
(=> packet get-checksum)
のように書けるようにすることも考えられるが、今度は、(rnrs)の=>と定義が衝突するため特別な配慮が必要になる。
- 継承
- インスペクション
汎用のパケットダンプに対する要求が意外に多いので、どうにかしてメンバを列挙するための仕組みを導入する必要がある。
- 評価されるキー
現状のyuniオブジェクトは、シンボルしかキーになれないという問題が有る。
配列(vector)や辞書を参照するためには、汎用ref/set! ( ~ ) 構文を使う必要があり、let-withやtouch!のような便利な構文が無い。