使うと「通常の3倍」の速度で OCaml のソースコードを理解できる OCamlSpotter

(その変態的シンタックスに慣れれば) 結構早くプログラムが理解できるとうわさの OCaml ですが、他人の書いた OCaml ライブラリを読んだり、自分が書いた物でも、コード規模が大きくなってきたりすると、

どこかにあるハズの定義が見つからねぇ

ってことが多くなってきます。例えば、

open M
open N

...
何百行もある
...
let compute () = 
  ...
  X.f
  ...

っていうソースがあったとして、 X.f の定義を探したいとき、どうしますか?普通は、こんな感じでやります:

  • x.ml というファイルがあれば、多分その中に f というのがあるはず => x.ml なんて無い
  • じゃあ、「何百行もある」の中にモジュール X が定義されてるかもしれないから、エディタでサーチする => 無い
  • あれー?じゃあ、どっか別のディレクトリの中に x.ml があるのか? find . -name x.ml => hoge/x.ml の中で let f = を発見!! あれ、でも、なんだか型が違うみたい。これじゃあ無いのか、、、
  • じゃあ、M と N を open してるから、M.f か N.f? => 無いんですよこれが
  • どこに有るねんコラ
  • 実は m.ml の中に N というモジュールあって、その中で f が定義されていました。「M.N.f のことか… M.N.f のことかーーーっ!!!」
  • その上、M.N は module N = F(Y) と定義されていて、本当の f の定義コードは Y にあったりして、、、
  • 既に10分経過しており、もともとの compute 関数が何をするものだったかすっかり忘れている。
  • それどころか、自分が compute 関数の定義を読んでいたことさえ、忘れている。

てな感じ。こんなモジュールを多用したカッコいいコードは、全体像を理解していると、結構読みやすいのですが、一見さんだったり、下手に open を使っていて名前空間が入り組んでいると、定義を見つけることがとても難しくなります。

OCamlSpotter は、(えっと、そもそも、このブログはこいつの広報として作ったんですよ…) コード読みにおける、このウザイ作業を自動化して、

高邁な皆様にはもっと純粋にコードのアルゴリズム理解にだけ集中して欲しい、

という願いを持って作られたツールなのであります。OCamlSpotter は、OCaml ソースがコンパイルされる際に解析されている変数、型、モジュールなどの名前(identifier)の定義や使用情報をコード位置と一緒に .spot もしくは .spit ファイルに書き出します。このデータを付属のツールを使って検索してあげることで、identifier の定義探しを自動的に行います。Emacs 使いには ocamlspot.el を用意してありますので、キーをパパッと押すだけで、カーソルの下にある名前の定義を別 window に表示させることができます。(Vim も原理的にはできますけど、ラッパを用意していません。だれかそういうのの判り易い作り方情報へのポインタを教えてくれたら作ってみてもいいですけど)

私の働いている会社では OCaml のコードで 100万行とかあるので、このツールがあると、ないとでは、大違いです。1query で 1$ くらい節約できてる! と言われましたが、その割には去年は[お察しください]

残念ながらこいつは OCaml コンパイラにパッチを当てる必要がありますので、コンパイラをご自分でビルドしていただかないといけません*1

えー、メンドクサ、.deb とか MacPorts ないの、などと、という方は、さようなら。

と言いたいところですが、今回から(前回からかも) BRAIN_DEAD_INSTALL.sh という運がよければ OCaml コンパイラのソース本体からパッチあてからコンパイルまで全部やってくれるお気楽ビルドスクリプトも付けておきました。うまくいかなかったらこのスクリプトを見れば大体ビルド方法がわかるから手でやってみてね。それでも嫌なら、もうしょうがないよ。そんな人ぁこんなツールが必要なほどそもそも OCaml 書かんから放っとこ。

Windows の方は、、、御武運をお祈りしています。(いや、まあ、普通にコンパイラをソースからビルドできる人なら、このパッチあててコンパイルするだけです。)

なお、コンパイラの型付けアルゴリズムとか、生成コードとかにはぜんぜんタッチしていないので、コンパイラとしては完全なる上位互換です。既に 3.11.2 でコンパイルされ、インストールされたライブラリとも仲良く使用できるはずです。(ただし、.spot が無いので定義探しは出来ませんが。)

で、今回は OCaml 3.11.2 対応の Version 1.1rc1 を公開

OCaml 3.11.2 が出たばかりですが、ちょうどよい機会なので、OCamlSpotter も 3.11.2 対応版を公開です。前のバージョンのバグフィックスだけでなく、検索対象の強化とか、もうちょっと使いやすい elisp とか、いろいろ頑張りました:

http://jun.furuse.info/hacks/ocamlspotter/

RC1 なのは、まー正式出荷には一週間位寝かしたほうがいいかなあと思ってです。

*1:さらに対象ソースをこの改造コンパイラに -annot オプションを付けてコンパイルして .spot/.spit ファイルを準備する必要があります。また、ライブラリをインストールする場合、.spot/.spit ファイルも同じところにインストールしてください。ソースの場所は .spot/.spit ファイルに書き込まれているので消したり、移動すると、当然ソースは探せなくなります。