2009-01-28

VC10のインテリセンスについて

Visual C++ Team Blog : Dev10 Is Just The Beginning

過去の記事
http://blogs.msdn.com/vcblog/archive/2007/12/18/intellisense-history-part-1.aspx http://blogs.msdn.com/vcblog/archive/2008/02/29/intellisense-part-2-the-future.aspx

我々が初めて C++のintellisense を実装したときは、想像以上に悲惨であった。まあ、ユーザはそれほど期待していなかったというのもあるのだが。何より早さが必要だった。しかし、テンプレートや複雑なオーバーロードで動かないというのであれば、不満も出るだろう。当然ながら、我々はC++コマンドラインコンパイラのフロントエンドを、インテリセンスにも流用したかった。が、それはintellisenseを考えて設計されたものではない。それは256Kのメモリを積んだ16 bit DOS上で実行できるよう設計されていた。ステートメントをひとつずつパースし、解析し、即座にアセンブリレベルのintermediate言語に落とし込むのだ。intellisenseに向いた設計というのは、字句解析と意味解析を分けておくものなのだ。意味解析は重い処理なので、intellisenseの為には、ユーザが知りたい部分にだけ適用したい。我々はintellisenseのために、新しいC++フロントエンドを書くことも考えた。結局我々の結論は、C++はとても複雑だ、ということだった。ひとつのプロダクトサイクルに間に合わない程、時間がかかるので、もっと手っ取り早くやりたかった。そこで我々は、コマンドラインのC++コンパイラを元に、ifdefを画期的に用いて、intellisenseコンパイラに仕立て上げた。我々はintellisenseコンパイラを、FEACPと呼んだ。Front End Auto Complete Parserの略である。コマンドラインコンパイラは、C1XXと呼ばれていた。これは、C++ phase 1の事だ。ifdefはC1XXコードから、あらゆるintermediate言語に落とし込む処理を省く為に使われた。また、必須でないと思われる意味解析も省いた。初期化、メンバオフセット計算、vtable生成など。当時のCPU速度は、たったの100MHz程度だったので、C1XXの多くのコードを削り、ドロップダウンウインドウを100ミリ秒以内に表示させる必要があった。必須でないメモリの使用も省かれ、シンボルに対する情報もわずかしか保持しなかった。これは特に重要な事だった。なぜならば、FEACPはIDEプロセスの中で動かなければならないからで、IDEはすでにかなりのメモリを使っていたからだ。

FEACPの製品化は成功したものの、そのテストとメンテナンスは悪夢であった。ifdefで削ったために、多くのコードやデータの依存性の問題があった。頻繁にクラッシュするし、NCBファイルが壊れることも多々あった。メンテナンスは重労働であった。というのも、FEACPとC1XXは、あまりにも異なっており、C1XXに対する、一日数百万行ものコードによるテストは、FEACPの品質にあまり貢献しなかった。かなり別々にテストするを余儀なくされた。教訓としては、二つの異なるコンパイラを、同じソースコードでサポートするのは、二つの完全に別なコンパイラをサポートするより、多少マシなだけであり、どちらも長期的なメンテナンス性では、あまり良い選択とは言えない。実を言うと、コンパイラは三つあった。ANSI-Cは、また別のifdefの塊だったからだ。本当は、四つあった。/analyze コンパイラを含めるならば。

FEACPをリリースした年に、我々はifdef地獄の行ける所まで突き進んでしまった事に気がついた。同時に、もっと単純な、JavaやC#といった言語に対するintellisenseの出来栄えが、ユーザのintellisenseに対する期待を、FEACPでは実現不可能なレベルにまで押し上げてしまっていた。今日の千倍早いCPU速度とメモリ容量では、FEACPを選択した、当時としての妥当な理由は、もはや成立しなくなってしまう。さらに、あまりに増えすぎたifdefとその結果のコンパイラモデルは、C1XXに対する言語機能の追加を困難にしてしまっていた。バグ数はうなぎ上りで、言語の差はいや増すばかり。それと同時に、十分な能力を持ち、C++コンパイラの仕事をしたいと思う者も減っていった。何とかしなければならない。

近年のPCの速度と容量であれば、ひとつのコンパイラで、C++のコード生成とintellisenseの両方を行えるはずである。我々に何が欠けていたかというと、ソースコードの high-level internal representation である。それさえあれば、intellisenseの要求するサービスに対して、representationを流し込むこともできるし、マシン語に落とし込むこともできる。フロントエンドを蝕む、何千個もの#ifdefは必要なくなるし、コンパイルのモデルもひとつですむ。テストにかかる労力も劇的に減る。新人のコンパイラ開発者も入りやすくなる。しかし、手放しで手に入るわけではない。GHzクロック速度をもってさえ、すべてのintellisenseのリクエストに対して、すべてのコードに完全なフロントエンドを実行することはできない。我々は、完全なフロントエンドを、期待される結果をもたらす、必要な部分にのみ適用する、新たなintellisenseのフレームワークを作らねばならない。まだやることはたくさんあるが、ひとつのプロダクトサイクルの中で実現できるはずだ。そしてやり遂げた。Dev10は、その結果だ。

ここまで読んだ読者は、こう疑問に思うことであろう。「ふむ、軽量化に成功したんだな。マイクロソフトにとってはいいことだろうよ。でも俺にとってはどうなんだ」と。intellisenseに最も重要な機能は、精度である。Visual C++は何百万行ものコードを、ビルドラボや世界中のPCで、毎日コンパイルし、5 / 9程度の精度を持っている。intellisenseがコマンドラインコンパイラと同等になるということは、同等の精度を持つということだ。これはC++のintellisenseにもたらす、最も大きな変化である。

精度が高いというのは、自動補完のドロップダウンで正しいメンバを得られる以上のことを意味する。その他の、不可能や無謀だった機能をも、可能にするのだ。例えば精度で言うと、intellisenseのパース中に見つかったエラーは、本物のエラーである。したがって、編集や閲覧中のエディタウインドウに、「さりげなく」表示することもできる。これはわざわざファイルを保存してビルドを始めなくても、警告が得られるということだ。

そのほかの精度の利点としては、データはコード解析や変形に使えるほどの精度だということだ。例えば、ソースコードのリファクタリングなどだ。Dev10では、expression-level のデータのアクセスを提供させるのは時期尚早だ。ユーザはソースコードのシンボルを眺められる。将来的には、ユーザがアクセスできるAPIを提供し、C++のソースコード対する高精度の情報にアクセスできるようにする。これはWindowsのC++に対する、まったく新しい解析や理解、生産性のツールの環境となるだろう。

2 comments:

rt said...

英語が苦手な身としては、こういった和訳は非常にありがたいです。

VC10のインテリセンスはSQL Server Compactベースになるようですし、
sdfファイルを直接参照するとインテリセンスのデータ構造がそのまま覗けて、
色々とおもしろいことが出来そうで楽しみです。

said...

初めまして。

なかなか興味深く記事を拝見させていただきました。

実はフリーでSQL開発環境を作っておりまして、SQLの入力支援機能(いわゆるインテリセンスの機能)も実装しているのですが、実装が相当汚くてちょっと気にしていたのです。

Microsoftが(金と人かけて)作っても汚くなってしまうなら、まあ、個人でフリーソフト作って汚くなるのはしようがないよね~なんて邪なことを考えてしまいます。 ;-P