見出し画像

プログラミング言語 Ada - 机の上で活躍した思い出の言語

当時、愛読していた bit 本誌の方でも時折取り上げられていた Ada ですが、臨時増刊の形でまとまった解説本として出版されました。言語仕様があまりに複雑だったのにもかかわらず原則としてサブセットを認めていないので、手近な環境で実際に使うことができるようになるまでには、かなりの時間がかかりました。当然、この本が出た時点では、ただ說明を読むことしか出来ませんでした。パソコンでは Pascal くらいしか使っていない段階で、複雑な型システムや並行処理、名前の公開・非公開と名前空間、パッケージやモジュールに入出力や例外処理といった、今でこそ当たり前のように扱えるようになった概念に触れることができました。

そもそも、この言語ですが、アメリカの国防総省が入札や保守で困らないために統一規格を策定しようとして作られたもので、なかなかキナ臭い出自です。確かにシステムの非互換性が原因でミサイルが明後日の方向に打ち込まれたらたまりません。この時代、コンピュータシステムは無限に進化すると信じられていた節があり(確かにシステムは進化するのですが、人間のほうが進化しないんですよね)、どんどん仕様が肥大化していき今でさえ、かなり複雑に見える仕様となりました(iAPX432に代表されるCISC問題と似ているかもしれない)。

当時から、こんな複雑なシステムを安定して保守できるのかという問題は指摘されていたようですが、OSやライブラリプログラムに任せられていたような仕様を言語の側に取り込み、異なるプラットホームであっても同じ動作を保証できるようにする挑戦は一定の成果があったのだと思います。とはいえ今でも整数型が何バイトなの?とかタイマーの精度がシステムによってマチマチという苦労が繰り返されているのは困ったものです。

Ada は基本的にAlgol 系の言語(Pascalも、この仲間です)で、関数であれば function、手続きであれば procedure などと書いてから中身を定義します。代入も = ではなく := ですし、ブロックは begin から end までです。

ALGOL

型システムが充実しており、基本型に対して範囲を指定したり、制約をかけた新しい型を派生させることができます。整数であれば上限と下限の指定ができます。浮動小数点であれば精度を明示することができます。処理系は、この情報を元に適切な実装を選択すれば良いわけです。また型に対して、その上限などの情報を取り出す仕組みがあります。この型に対して制約を超えた場合には処理系は例外を発生させることが決められているので、例えば配列の添字に対して範囲内であることが保証されるのです。また可変部を持つ構造体を定義することができるので、いわゆる共用体もこの形で使うことになります。参照はポインタではなく、集合として宣言されている変数のウィンドウのような形で整理されていて、派生型を元の型の名前でアクセスすることを可能にするのが目的のようです。

関数や手続きを呼び出す際の引き数渡しにおいて、in/outを指定することにより、呼び出し側と呼ばれた側のどちらが値に対して責任をもつのかが明示できます。この指定で呼び出し元と呼ばれる側の変数が結合されるのであって、値渡しであるとか参照渡しという概念を持ち込まないようにしています。引き数の省略についても明文化されていて、引き数の数や型に応じて同じ名前の関数や手続きを多重定義することも可能となっています。

パッケージとして扱われる関数や手続きに対して、宣言と本体を分離することが決められており、本体を参照しなくても適切な型チェックが行えるようになっています。またパッケージに対して名前空間を提供し、名前空間の省略もできる方法が提供されています。またパッケージの外から見える情報と内部のみから見える情報をしっかりと区別していて、実装の適切な隠蔽が可能となっています。

タスクという特別な型を用意することで、並列処理を言語仕様の中に取り込んでいるのが特徴です。タスクに対しては、待ち合わせによるインターフェースが用意されており、タスクとの通信方法が明確になっています。結果を得る際には制限時間を指定することが出来るので、デッドロックを検出するだけではなく、タスクに異常が生じた際に処理を打ち切ることもできます。

例外の発生と、その伝達手順が定義されています。特にタスクとの例外の伝達が明示されているのは珍しいです。

主だった特徴を書いてみましたが、他にも複雑な型であっても、どのようにリテラルで初期化するのかであったり、リテラルも使って良い文字の集合や数値の基数も選べるようになっており、環境による差異がでないように細心の注意が払われているのがわかります。

Ada は、クラスもなく、いわゆるオブジェクト指向な言語ではありませんが、オブジェクト指向に必要な機構は用意されていて、大部分の演算子は型に合わせた定義もできます。OS毎に異なる実装を避け、多くの機構を言語自身に取り込むことで、環境が異なっても互換性が保てるように考えられているのがわかります。

もっとも、これだけの仕様を実装するのは大変で、言語で規定された条件を満たすためには、かなりの余分な仕事をする必要があり、結局のところ充分なパフォーマンスを出すためには、適宜、いろいろなチェックを省くといった指定をする羽目になったのではないかと想像します。今はLinuxにもパッケージが提供されていて、その気になればすぐに使えるのですが、殆ど使われることが無いようです。

この言語を理解することで、その後に登場したプログラミング言語において、ここで出てきた概念がどのように定義、実装されているのかを調べることで、言語の特徴を良く理解できるようになりました。C++を覚える際にも、予め派生型の定義であるとか、演算子の多重定義がどのように使われるかがわかっていたことはとても役に立ちました。スレッドはC/C++では言語ではなくライブラリで提供されますが、並列処理が理解できていれば、さほど苦労せずに使いこなせるようになりました。そういう意味で実際に使うことは殆どなかったのにも関わらず、自分にとってはとても思い入れのあるプログラミング言語です。

bit 1981/10 臨時増刊 - 入手は困難かもしれないですが、運が良ければ図書館などにはあるかも

Ada


この記事が気に入ったらサポートをしてみませんか?