Common Language Infrastructure

以下、去年の 11 月ころに書いた雑文。興味があって調べて書いたまではいいんだけど何故か entry として投稿しなかったという経緯で。いま C# やってるしいいか的な。

複数の言語間でうまくやりとりができるように Microsoft が策定した仕様のことらしい。一貫して OO: Object Oriented な感じ。おれはまたてっきり Microsoft が好きな closed な仕様かと思ったんだけど標準化もすでに問題ないレベルで驚いた。

以下 Ecma-335 の記述を base にいろいろ見ながらおれの中で理解、分解、再構築。無駄に長い。

  • assembly
    • 機能単位で実装された実行可能な code module や resource の集合。
    • 実行可能な code module ってのは具体的には処理内容を CIL に変換したものと manifest や metadata なんかの実行時に必要な情報のことを指しているのかなたぶん。で、 resource ってのがそのほかの画像やら locale data やらの単に参照されるもの、と。
    • これは http://msdn.microsoft.com/ja-jp/netframework/ee624169.aspx みたほうが速い ( 実装の説明をしている page だけど ECMA-335 にも同様の意味で同じ言葉が出てくる ) 。
  • CIL: Common Intermediate Language
    • VES ( 後述 ) が理解できる命令集合。
    • で、実際の命令群を見てみると assembly 言語に似てる感じ。 CLI 準拠の各言語で書いた code を compile すると処理内容がこの言語に変換される、と。いってみれば CLI という枠の中で最大の分解能を持つ言語なわけだな。
  • manifest
    • assembly の以下の情報を格納している部分。
      • version
      • name
      • culture
      • security 要件 ( security requirements としか書かれてない )
      • assembly に含まれる file の一覧とそれらの暗号化された hash
      • assembly で定義された型が他の assembly でも使用可能かどうか
      • manifest 自体の digital 署名と検証用の公開鍵 ( optional )
    • assembly が参照される際にここの data を見て参照すべきものかどうかとか参照してしまって問題ないかどうかを判断するのかな。これちゃんと version も見て判断するんだろうか。そうだとしたら下位互換性に労力を割かなくてもいいということだからすごいことだよな。あーあと各 locale で別 assembly にできるから locale 追加したから make し直しとかなくなるし locallization 用 SDK を本家で公開しやすいということにもなるなぁ。
    • あとは security check の overhead はどうすんだろう。昨今の machine なら大丈夫という折り込み付き、ということはないよねいくらなんでも。最初に参照される際に check した結果を cache するのかな。となると assembly の更新時間なんかは手動でいじれないという保証がないといけないから…、 assembly を管理する実体の実装による、ということはやっぱり実装依存というハナシになるのかな。まぁ仕様の段階で overhead のハナシをするなというそもそも論があるか。
  • metadata
    • CTS によって定義されている型を記述 & 参照する data 。
    • ってわかりにくいけど要は単純に class interface の定義をしている ( CLI はそもそも OO が根底にあるわけだから型はつまり class ということ ) わけだな。 C++ でいう ( class の宣言のみが含まれている ) header file のようなもんか。 CTS に準拠していることで他の assembly との相互参照性を担保している、と。
  • VES: Virtual Execution System
    • CTS を実装し実行する system で、 CLI 準拠の program の読み込み・実行を行う。 metadata を使って module 間の接続を行ったり managed code を実行するための service を提供する、と書いてあるけど。
    • 具体的には assembly 間の依存解決と JIT: Just In Time な compile による native code の生成、そして演算や method 呼び出しなどの実行、というのが主な役目らしい。他にも扱える型の定義とか型変換を行えるとか thread を管理できるとか method 呼び出し時の引数や返り値の処理ができるとか memory 管理ができるとか program の制御ができるとかそのために必要な instruction set の定義とか例外処理ができるとか、細かい規定がいっぱいある。
  • managed code
    • CLI が一連の core service を提供することを可能にする十分な情報を含む code 。たとえば code 内部の method に対する address が与えられたとき、 CLI は metadata においてその method の記述を発見することが可能でなければならない。また stack の走査、例外処理、そして security 情報の保存と参照も可能でなければならない。
    • core service ってのは VES で提供されるものという認識でいいのかな。っていうのはまぁ VES の説明のところに managed code って言葉が出てくるからなんだけど。
    • 他にも managed data ってのもあってこっちは garbage collenction を行うことによって CLI が自動的に確保したり解放したりする data のことらしい。
  • CTS: Common Type System
    • CLI そのものの他に compiler や tool によっても共有される統一された型システム。 CLI が型を宣言、使用、管理する際に従うルールが定義されているモデル。言語間の統合や型の安全性、高効率な code の実行が可能になる。
    • 型に関する標準を提供するらしい。具体的には型名、属性、定義方法その他もろもろ。
    • 確かに型が共通化されてるってのはかなりの強みだし、これが宣言時だけじゃなくて使用時にも言及されてるっていうのもかなり楽になるよね。型が共通化されてないとたとえば構造体という仕組み ( もっと普遍的に言うと型を組み合わせて新しい型を作るという概念 ) がある言語とない言語ではそもそもやりとりが不可能だったり、同じ概念でも言語によって違う言い方をしてると型変換が必要になるからそのために両方の言語での型の定義を知ってないといけなかったり ( code 書く人の負担が増える ) 、型変換にも cost がかかったり ( 実行する machine の負担が増える ) 、ちょっとこみいったところでは cast の安全性が確保されなかったり ( みんなに負担 ) とかパッと思いつくのだけでもたくさんある。
    • てか cast が安全になる ( というかある data に対しての解釈を変更することが適切にできる。言い方を変えると視点を変えられるということかな ) というのは普通にすごい気がする。 code の管理や効率的な開発という意味では意図的に使うものではないけどある概念について各人がいろいろな表現をしても何とかなるということが担保されているのはおもしろい。
    • ちょっと見てみたけど組み込み型の長さは Int8 だとか Int16 だとか、数字を伴って定義されてるみたい。まぁこのほうが誤解がないというか、歴史的に integer の略である int を 1 word だと定義したこと自体が間違っていたというか、そのせいで short だとか long だとかわけのわからない修飾子がつくことになったというか。 integer は整数って意味しか持ってないんダスよ !!
    • あああ native size とかいうのも定義されてる。これは実行する CPU が処理できる bit 数という意味だね。だからこの型を使ったときの実際の長さは 32bit CPU と 64bit CPU で異なる、と。で class library 側ではこれを IntPtr として対応させているのでいわゆる pointer として扱うということなんだね。ほぇー、かなりしっくりきた。
  • CLS: Common Language Specification
    • 言語設計者と framework ( class library ) 設計者の間での合意。 CTS の subset で使用規約の集合。
    • と書いてあるので普通の開発者は関係ない、はず。中身も言語の予約語がかぶらないようにしようとか framework user が nest した型を書けないようにしようとかそういうことが書いてるから多分そう。
    • CLI 準拠言語を作ってやろうとか逆 assembler 書こうとかいう場合には参照してねってことだね。 CLS を拡張することもできるみたいだけどこれはかなり変態的なことをやる場合のハナシかなぁ。
  • Library
    • ひとつ以上の assembly に分類された、型一式が入っているところ。他の library で定義された型に対する変更、たとえば method や interface 、例外の追加などを含むことも出来る。
    • 型てのはつまり class のことだから後半部分も意味が通る、と。で、標準化されている Library に以下のものがあるみたい。
      • Runtime Infrastructure Library - compiler が必要とする service を提供したり metadata から動的に型情報を読んだりすると書いてあるけど実行時に必要な class の定義がなされている Library という解釈でいいのかな。
      • BCL: Base Class Library - 最近の言語にとっては単純な runtime library で CLI Standard Library としてや C# 言語にとっての runtime library の Standard として、 CLI の組み込み型、単純な file access 、 custom attribute 、 security attributes 、文字列操作、書式設定、 stream 、collection ( data の集合体のことかな ) を提供する、と書いてある。いきなり C# とか出されても困るんだけど ECMA-334 ( http://www.ecma-international.org/publications/standards/Ecma-334.htm ) で標準化されているのでそちらを参照しろということか。なんというかとりあえずまぁ基本的で原始的な level の機能を提供する Library なんだな。
      • Network Library - HTTP はもちろん port への直接の access を含む network service を提供する。これはそのままだな。
      • Refleciton Library - 型に対して、構造の検査、 instance 生成、そして method を呼び出す能力を提供する。すべて型の記述を基に行われる。で、 must support が指定されている、と。たとえばある Library 内の class に対する変更が別の Library で行われている場合に VES がそれを適切に処理するためにこの機能が必要だったりするから CLI の根幹を為している部分でもある、と言えるね。余談だけど reflection て code からの視点でつけた名前なのかな。自分の姿が data として見える -> 鏡で反射してるみたい -> 反射 -> reflection みたいな流れ。
      • XML Library - 単純な pull 型の XML parser を提供する。 resource に制約のある device を考慮に入れて設計されているが、単純な user model を提供する。 XML Library を含む CLI 準拠の実装は Network Library も実装すべきである。そのままだね。
      • Extended Numerics Library - 浮動小数点数型 (System.Single, System.Double) と拡張精度数型 (System.Decimal) の support を提供する。 Base Class Library のようだが、この Library は C# Standard によって直接表される。 なんで BCL に含まれないのかっていうと浮動小数点数計算 を support してない CPU も存在するからだって。ここが実装されてない場合に浮動小数点数使おうとすると例外が飛ぶようにしとけとか書いてあるから must じゃないのね。
      • Extended Array Library - non-vector な配列の support を提供する。それは 1 次元以上かつ 0 が下限でない配列のことである。要は添え字が 0 以外からはじまる配列のことらしい。
      • Vararg Library - 可変長引数の処理の support を提供する。 C 言語とかそのあたりからの流れ的にはここらへんの処理を pointer を使って書くというのはそんなに大変ではないと思うんだけど、どういう形式で使うんだろう…。 syntax sugar ならわかるんだけど Library で定義されているというのはちょっとよくわからない。言語間の溝を埋めるという意味で最近の scripting language ぽい記法も support できますよ、ということなのかな。
      • Parallel Library - thread 処理を提供するらしい。簡単に扱えて言語間で違いがないのが目的とか。
  • Profile
    • Profile は一定水準の機能性を提供する同様の Library の集合。
    • ってことだけど比較的粒度の大きいハナシをするときに使う言葉なのかな。とりあえず標準化されてるのは CLI 準拠のためには必須の Kernel Profile ( Runtime Infrastructure Library と BCL を内包する ) と物理的 resource が乏しければ省いてもいい Compact Profile ( 同様に Kernel Profile ・ XML Library ・ Network Library ・ Reflection Library ) の 2 つのみだけどこれは CLI を実装する際に複雑にならないようにするためだそうで。あとは特定機能をもつ Profile を追加していくことができる ( たとえば数学用とか金融用とか ? ) というのも market が大きくなっていいよねとか皮算用的なことまで書かれてる。まぁ Profile 単位で切り分けという概念があれば特定の実装に対して 3rd party が Profile を release しやすくなる、というのはわかるしこれは工業用の仕様標準化なのでこれが正解なのか。

と、こんなもんかな。感想はー、ここまで見てきてやっぱり最近の Microsoft がんばってんなぁというのがまず出てくるよね。標準化や仕様公開の重要性がわかってきたのかそこらへんをちゃんと進めているところは特に。これは普段悪いことやってるヤツがいいことするといいやつに見えるというのと共通するな。あとはけっこうこの仕様書あいまいなところが多いというか読みにくいというか、せめて SHOULD / MUST / MAY くらいは矛盾なく明確にして欲しかったぜ。

でまぁ、 CLI 自体かなりでかいっていうかまぁ要は OS level の仕様を決めてるわけよね ( threading とか memory management とか machine 間の差異の吸収とか Library という API とか ) 。今はまだ既存 OS の上に VES を載っけてる段階だと思うんだけど多分 VES のことを OS と呼ぶ時期もくるはずで、 Microsoft もそういうところをにらんでいそうな気がする。あーでも Java も似たような感じだけど Sun はそういう方向に持ってこうとしなかったのかな。なんでだろう。 Java 知らんからわからんな…。

最後に、たしか .NET Framework って言葉が出てきてたときにちょうど Microsoft の社員の人のハナシを聞く機会があったんだけどその時点では何がうれしいのかわからなかったというか、ちょうど言語間の整合性の取り方とかで OMG ( http://ja.wikipedia.org/wiki/Object_Management_Group ) が model っていう抽象概念と言語の mapping を考えればいいじゃない !! とか言っててあー何いってんだこのひとたちはとか思ってたので同じような感じで処理してたんだよね。

で、実際に今 CLI ってものを見てみると CIL が言語の間にたって mappinng を可能にしているという風に見えてしまったという。てかたぶん現行の実装で C# で書いた code を MSIL を介して VB.NET機械的に変換することってできるよね ( http://www.red-gate.com/products/reflector/ とか ? ) 。これができるってことは CLI の実装で support されている言語のうちひとつでもできれば一緒に開発が出来る ( 適当な VCS中間言語の形でつっこんでおいて参照 / 変更時に好きな言語を選択できるとか ) ということなので人材の確保が容易になるってことでもあるからすごいと思うんだけど実際のところはどうなんだろう。まぁ言語によっては得意不得意な分野があるから一筋縄ではいかないだろうし、まだそんなに変換の精度が高くなかったりするという現実があるのかなぁ。

ここらへんをもう少し引っ張っていくと自然言語にも適用できそうというか、たとえば Esperanto のように規則的に意味を取り込んでいける言語を base にして最大の分解能を持つ言語を作ることができれば機械的にそれなりな翻訳ができると思うんだけど難しいかな。言語によって微妙なニュアンスが重要だったりするのでそれをきちんと mapping しようと思うと中間言語の文法は複雑すぎるものになると思うし、そもそもそんな分解能を持つ言語の maintenance てかなり大変だと思うんだよね。いやいやそういう統一言語を作ってしまったらそれを使えばいいじゃないというハナシなので翻訳とかは old-type のためのものになるとかそういう宇宙世紀的展開 ? ちょっとまてたとえば人類の知らない言語 ( 他恒星系の知的生命体でも生き別れた人類でも進化した爬虫類でもなんでもいいけど ) を取り込もうという段階でここらへんをやっておくと楽になりそうというか。言葉の違いが争いの元という小咄が古いオハナシにもあるわけだしな。

なんだこの妄想。