Bは、 1969 年頃にベル研究所でケン・トンプソンとデニス・リッチーによって開発されたプログラミング言語です。
BはBCPLに由来しており、その名称はBCPLの短縮形である可能性もある。トンプソンの同僚であるデニス・リッチーは、その名称は、トンプソンがMultics向けに設計した、それ以前の、しかし無関係なプログラミング言語であるBonに由来しているのではないかと推測した。[注 1]
B言語は、システムソフトウェアや言語ソフトウェアなど、再帰的、非数値的、機種非依存のアプリケーション向けに設計されました。[3] B言語は型を持たない言語であり、そのデータ型は、基盤となるマシンの自然なメモリワード形式(それが何であれ)のみでした。文脈に応じて、ワードは整数またはメモリアドレスとして扱われました。
ASCII処理機能を備えたマシン、特にベル研究所に導入されたDEC PDP-11が普及するにつれ、メモリワードに格納された文字データのサポートが重要になりました。言語の型を持たない性質は欠点と見なされ、トンプソンとリッチーは新しい内部型とユーザー定義型をサポートする拡張版を開発しました。これが後に広く普及したCプログラミング言語となりました。
SMALGOL構文を多く含むBCPLセマンティクス
— ケン・トンプソン、[4]
1969年頃、ケン・トンプソン[2]と後にデニス・リッチー[3]は、主にトンプソンがMulticsプロジェクトで使用したBCPL言語をベースにBを開発した。Bは本質的には、当時のミニコンピュータのメモリ容量に収めるためにトンプソンが不要だと感じたコンポーネントを取り除いたBCPLシステムだった。BCPLからBへの移行には、トンプソンの好みに合うように変更も含まれていた(主に一般的なプログラム内の非空白文字の数を減らす方向)。[2] BCPLの典型的なALGOL風の構文の多くは、この過程でかなり大幅に変更された。代入演算子はRutishauserのSuperplanのに戻り、等号演算子は に置き換えられた。
:=====
x =+ yトンプソンは、yをxに加算する構文(C言語では と表記+=)を用いた「2アドレス代入演算子」を追加しました。この構文は、Bのコンパイラが初めて実装されたダグラス・マキロイによるTMG実装に由来しています(TMGではALGOL 68のx +:= y構文から派生しています)。[2] [5]トンプソンはさらに進化し、インクリメント演算子(++と)とデクリメント演算子( --)を発明しました。これらの演算子の接頭辞または接尾辞の位置によって、オペランドの変更前に値が取得されるか、後に取得されるかが決まります。この革新はBの初期バージョンには存在しませんでした。デニス・リッチーによると、これらの演算子はDEC PDP-11の自動インクリメントおよび自動デクリメント・アドレスモード用に作成されたとよく考えられていますが、Bが最初に開発された当時はマシンが存在しなかったため、歴史的にこれはあり得ません。[2]
forループのセミコロンバージョンは、スティーブン・ジョンソンの研究からケン・トンプソンによって借用されました。[6]
Bは型を持たない、より正確にはコンピュータワードという1つのデータ型しか持たない。ほとんどの演算子(例えば、、、+)はこれを整数として扱ったが、他の演算子はこれをデリファレンスされるメモリアドレスとして扱った。その他の多くの点で、BはC言語の初期バージョンによく似ていた。いくつかのライブラリ関数があり、その中にはC言語の標準I/Oライブラリの関数に漠然と似ているものも含まれている。 [3]
Thompsonの言葉を借りれば、「Bと昔のC言語は、[C言語の]型を除けば非常によく似た言語だった」[6] 。-*/
初期の実装は、初期のUnixを搭載したDEC PDP-7およびPDP-11ミニコンピュータ、およびオペレーティングシステムGCOSを搭載したHoneywell GE 645 [7] 36ビットメインフレーム向けでした。初期のPDP-7実装はスレッドコードにコンパイルされ、リッチーはTMGを使用してマシンコードを生成するコンパイラを作成しました。[8] [9] [10] 1970年にPDP-11が購入され、移植にはスレッドコードが使用されました。アセンブラ、 直流、そしてB言語自体もコンピュータのブートストラップのためにBで書かれていました。yaccの初期バージョンはこのPDP-11構成で作成されました。この間、リッチーがメンテナンスを引き継ぎました。[ 2] [10]
B言語の型なしという性質は、Honeywell、PDP-7、そして多くの古いコンピュータでは理にかなっていましたが、PDP-11では問題となりました。PDP-11やほとんどの現代のコンピュータが完全にサポートしている文字データ型にエレガントにアクセスすることが困難だったからです。1971年から、リッチーはコンパイラを機械語に変換する過程で言語に変更を加え、特に変数のデータ型追加が顕著でした。1971年から1972年にかけて、B言語は「New B」(NB)へと進化し、その後C言語へと発展しました。[2]
B言語はC言語に取って代わられ、ほぼ絶滅した。[11]しかし、小規模システムにおけるハードウェアの制限、膨大なライブラリ、ツール、ライセンス費用の問題、そして単に仕事に十分であることなど、さまざまな理由から、 GCOSメインフレーム(2014年現在[アップデート])[12] や特定の組み込みシステム(2000年現在)では引き続き使用されている。[11]非常に影響力のあるAberMUDは、もともとBで書かれていた。 [アップデート]
以下の例はケン・トンプソンによるBのユーザーリファレンスからの抜粋です: [3]
/* 次の関数は、2<=b<=10 となる、b を基数とする非負数 n を出力します。このルーチンは
、ASCII 文字セットにおいて、0 から 9 までの数字が連続したコード値を持つ という事実を利用しています
。 */
printn ( n , b ) { extrn putchar ; auto a ; /* Wikipedia の注記: auto キーワードは、C++11 のような「自動型付け」 ではなく、自動ストレージ (有効期間は関数スコープ)を持つ変数を宣言します 。 */
if ( a = n / b ) /* 代入、等価性テストではない */ printn ( a , b ); /* 再帰 */ putchar ( n % b + '0' ); }
/* 以下のプログラムは、定数e-2を約
4000桁の10進数で計算し、
5文字ずつ50文字ずつ1行に出力します。この方法は、
1/2! + 1/3! + ... = .111... という展開式を単純に出力変換したものです
。ここで、数字の基数は2、3、4、...です。 */
main () { extrn putchar , n , v ; auto i , c , col , a ;
i = col = 0 ;一方( i < n ) v [ i ++ ] = 1 ;
while ( col < 2 * n ) { a = n + 1 ; c = i = 0 ; while ( i < n ) { c =+ v [ i ] * 10 ; v [ i ++ ] = c % a ; c =/ a -- ; } putchar ( c + '0' ); if ( ! ( ++ col % 5 )) putchar ( col % 50 ? ' ' : ' * n ' ); } putchar ( ' * n * n ' ); }
v [ 2000 ];
n 2000 ;
ジョンソンのforループのセミコロンバージョンを見て、[B]にそれを入れました。盗用です。