gcc-4.7のAdaの変更点

公式Release NoteのAdaのところが相変わらず手抜きなので、いつものようにメモっときます。
今回はなぜかAdaCoreが本気出してて、gccがStage 3(バグ修正のみのフェイズ)に入ってもガンガンコミットされてたりしてたので、最後まで追いきれてないです。ウォッチャーするのも根性がいるのです。
なお相変わらず、Bugzillaは放置されてます。AdaCoreはgccのBugzilla使ってないのでしょうか?
D言語(のように開発が他で活発に行われているフロントエンド)がgccリポジトリに入っても同じような状況になるんでしょうか?gccの開発体制とか全くわかりません!コミュ障です!

Ada2012対応

use all typeが部分的に使えます。
といっても変数を初期化する式でだけです。(V : T := X;のXでだけ。V := X;のXはダメでした。)
早く全面的に使いたいですねー。

aliased引数が使えます。

aspectのみの機能も実装されてきています……って書くと分かりづらいですね。
Ada2012のaspectC++0xで言う属性です。__attribute__(())です。Ada2005までは全部pragmaで後置していたのですが、宣言と一緒に書けるようにしたものです。
構文自体は4.6から受け付けるようにはなっていたのですが、既にpragmaとして存在する機能のみの対応でした。
4.7では、aspectの形でしか存在しない新機能にも対応しています……ってことですハイ。

Implicit_Dereferenceが作れるようになりました。
C++で言うと追加データやデストラクタも持てる参照型です。あるいは暗黙のキャスト演算子をひとつだけ持てるstruct。
(以前試したときは関数呼び出しの返値でのみ解釈されてましたが、オブジェクト単体でも解釈されるようになってます。やったー。)

range-based for(違)も実装されました。
Ada.Iterator_Interfacesもちゃんとあります。
展開されたコードを見ると冗長だなあ……と思いますが、Iteratorの型がForward_Iterator'Class(要するにサイズ不定の型)でFirstもNextも仮想関数で、Referenceの返値もデストラクタを持ってることを考えますと短くなりようもないですしね。
(-O3でコンパイルして、ループごとに仮想関数×1、非仮想関数×2の呼び出しが追加で必要。そんなもん?)

operator [] (違)も実装されました。
規格では右辺値ならConstant_Referenceが呼ばれるみたいなことが書いてある気がするのですがConstant_Reference/Referenceの呼び分けはコンテナ自体がconstant(in)かどうかしか見てないようです。
現在のAda.Containersの実装ではConstant_ReferenceとReferenceに差が無いので関係無いです。
俺々コンテナを使うときはReferenceが呼ばれることによるパフォーマンス悪化に注意、でしょうか。
(以前試したときはConstant_Referenceも「参照型」を返す関数のみ受け付けてましたが、Iterator_Elementの型をそのまま返す関数も受け付けてくれるようになってます。)
あと2引数以上の時の挙動はバグっぽいです。

QueueとかMultiway_Treeやなんかのコンテナも実装されました。

Synchronous_Barriersやなんかの同期オブジェクトも実装されました。

Subpoolも実装されました。
libcで言えばmalloc_zoneみたいなやつです。
もちろんmallocで取ってきたメモリを独自管理してますので、malloc_create_zoneやHeapCreateを直接使うのと比べて二重管理ry

その他改善点

Controlled型(C++風に言うとデストラクタのある型)がリンクリストを作らなくなってます。
以前は同一スコープのControlled型はリンクリストでつながってて、スコープを抜けるときはリストを辿って終了処理が行われていました。
つまりオブジェクト毎にポインタ2つ分の余計な領域が取られていたわけですが、これが無くなりました。
でもリンクリスト自体が無くなったわけではなく、スコープごとにFinalization_Masterなるものが作られるようになって、これがリンクリストを持っています。要するに侵入型リンクリストが外付け型になっただけ。
なので依然としてBoehm GCを使ってもControlled型は自動では解放されません。

Unbounded_Stringのデータが参照カウンタで共有されるようになりました。
(以前試したときはデフォルト無効だったのですが、デフォルト有効になってました。めでたしめでたし。何度も書いてますようにネイティブで可変長文字列を持つ言語と比べるとやっぱり見劣りしますが、とりあえずstd::stringを見上げることはなくなりました。)

protected型がread-write lockしてくれるようになってます。
今まではprotected procedureもprotected functionも同じ排他制御がなされてたのですが、protected procedureはwrite lock、protected functionはread lockされるようになりました。
(ここでfunctionは副作用なしというスタイルを心がけて云々と言えないのが辛いところです。Ada2012ではfunctionもin out引数を持てるようになって、副作用のあるfunctionの利用が加速しています。世の中が関数型に傾倒しているというのに、昔っからfunctionの引数がin固定だったりpackageがpureであることを明示できたりしてて素地があったはずのAdaは見事に逆行してます。)

他のフロントエンドから投げられたも受け止められるようになっています。
System.Exceptions.Foreign_Exceptionにマップされるようです。
これでミックスランゲージも大丈夫!
(以前、他のフロントエンドから投げられた例外はwhen othersでは受け止められないみたいなことを書きましたが、一年持たずに嘘記事になりました、めでたしめでたし。)

Formal_コンテナが追加されています。
Bounded_コンテナの実行時エラーチェック強化版?

MKS単位系付きの書式化出力ルーチン群が追加されています。
よくわかりません!

他にも新pragmaとかいっぱいありそうですが把握できてません!

みんなのホームディレクトリ下の構成を教えてください

http://d.hatena.ne.jp/ku-ma-me/20120330/p1

晒してみます。こないだ再インストールしたばかりですのでまだあまり汚れてません。

$ ls -a | cat
.
..
.CFUserTextEncoding
.DS_Store
.FontForge
.Trash
.Xauthority
.Xcode
.bash_history
.bash_profile
.config
.darcs
.emacs.d
.fontconfig
.gdb_history
.gitconfig
.gitignore
.inkscape-etc
.lftp
.local
.ocaml_history
.ssh
.subversion
.viminfo
.w3m
.wine
Applications
Desktop
Documents
Downloads
Library
Movies
Music
Pictures
Public
Sites
projects

なんてことはないSnow Leopardデフォルトのまま。~直下に自分で作ったディレクトリは~/Applicationsと~/projectsのふたつだけです。

あとパッケージマネージャはHomebrewを使っています。*1

~/Applications/ # ここにアプリを放り込む。/Applicationsはなるべく汚さない。インストーラ付きのものは諦めてます……
~/Applications/bin/ # 各アプリのbin以下のファイルへシンボリックリンク。スクリプトとかも放り込んでます
~/Applications/Homebrew/ # Homebrewのインストール先
~/Documents/ # プログラムに関係ないファイルはここ
~/Pictures/ # なぜか人狼とFontForgeの作業空間に
~/Site/ # ローカルCGIとか自サイトのミラーとか
~/Site/SandTrip/ # 神プラグインだったSandTrip用CGI置き場。64bitでは使えないのでゴミと化しました……
~/projects/ # リポジトリのcheckout/cloneはこの下で
~/projects/build/ # 野良ビルド空間。ビルドしたときの手順はテキストファイルに残してgitで保存
~/projects/experimental/ # 実験場

PATHは↓のように通してます。*2

PATH=~/Applications/bin:~/Applications/Homebrew/bin:$PATH

~/binや~/localではない理由は、これらの名前はFinder*3で一番上にくるためです。~/projectsを一番上に持ってきたかったですからね。(~/Applicationsはローカライズされて「アプリケーション」と表示されてます)

で、ホームディレクトリとは別に次のディレクトリにもファイルを置いています。

/usr/local/ # gccをインストールする場所
/usr/local/bin/ # gcc以外にもTextWranglerのツールも(「Install Command Line Tools...」を実行したら選択の余地なく)入ってます
/usr/local/i686-pc-freebsd7/ # クロスコンパイル用
/usr/local/i686-w64-mingw32/ # クロスコンパイル用
/usr/local/lib/ # GMP, MPFRなんかもUniversal Binary化してここに入れました
/usr/local/quartz/ # /usr/X11/やHomebrewと干渉するライブラリ置き場
/書庫/ # ~/Downloadsから昇格したファイルを置いています。wgetするのもここ。
/書庫/Backup/ # 手動ローカルバックアップ。一応ホームディレクトリの外に作りました。

野良ビルドしたライブラリは/usr/localに置いてます。ここなら-L指定しなくていいですので、サボりです。
あらかじめDESTDIR指定で別の場所にインストールしてUniversal Binary化の作業*4をして、それをdmg*5にして取っておいて、それからsudo cpって手順を踏んでますので変なファイルは入りません……はずです。

/usr/local/quartzには、X11と衝突するライブラリを置いています。Quartzバックエンド*6を有効化したcairoやgtk+みたいな。
使うときは↓のようにします。*7

export PKG_CONFIG_LIBDIR=/usr/local/quartz/lib/pkgconfig/

「書庫」は、どうせターミナルからアクセスすることはないやーと思ってFinder上で一番下にくるように日本語名にしたのですが、アーカイブファイルを展開するなどで案外アクセスすることがあって悩んでます。

ベストプラクティスは私も教えて欲しいです。

*1:OS X特有の事情について。
OSXでは、MacPortsFink、Homebrewというパッケージマネージャが鎬を削っています。私の環境は、Homebrewの都合が色濃く出ているため、OS Xユーザーのうち更にHomebrewを選択した人のうち更にHomebrewのデフォルトの振る舞いが気に入らない人、という超狭い対象向けのディレクトリの切り方になっています。晒しといてなんですが真似するのはおすすめできません。サーセン
最初この事情を書いていなかったため混乱させたようです。そして遠藤さんの感想→https://twitter.com/#!/mametter/status/185725646431993857
Linuxディストリビューションごとにパッケージマネージャは固定でしたっけ……そっちを意識してませんでした……。

*2:Homebrewのデフォルトのインストール先は/usr/localですのでPATHを通す必要はないのです。ところがこのHomebrew、/usr/localのアクセス権を勝手に変えたりします。ので私はホームディレクトリ以下に配置しました。

*3:標準のファイルマネージャ。

*4:32ビットと64ビットを混在させるための魔術←手抜き説明。

*5:OS X標準のアーカイブ形式。

*6:QuartzOS XのネイティブGUIです。それとは別というかその上のレイヤーとしてXサーバーもあるわけです。

*7:HomebrewはなるべくX11を使うようになっています。MacPortsですとvariantで最初からQuartz向けにビルドできたりしますのでこんなことは不要です。