プログラミング言語

プログラミング言語（プログラミングげんご、英: programming language）とは、コンピュータプログラムを記述するための形式言語である。なお、コンピュータ以外にもプログラマブルなものがあることを考慮するならば、この記事で扱っている内容については、「コンピュータプログラミング言語」（computer programming language）に限定されている。
プログラム言語ともいい、日本産業規格の JIS X 3000 シリーズの規格名称では、全て「プログラム言語」になっている（例： JIS X 3001 プログラム言語 Fortran、JIS X 3014 プログラム言語 C++）。個々のプログラミング言語の名称は、「言語」だけを接尾辞として用いた「C言語」のような表記をすることが多い。

自然言語との違い

プログラミング言語は、人間がコンピュータに命令を指示するために作られており、コンピュータが曖昧さなく解析できるように設計されている。多くの場合構文上の間違いは許されず、人間はプログラミング言語の文法に厳密にしたがった文を入力しなければならない。
これに対して、一般に自然言語の文法規則はプログラミング言語にくらべてはるかに複雑であり、例外も多い。ただしこれは規則が一般にいいかげんであったり、曖昧であるということではない。一般に自然言語の規則は奥が深く、驚くほどの非合理性に裏打ちされていることもあれば、驚くほどの合理性に裏打ちされていることもある。驚くほどの非合理性でも合理性でもないものに裏打ちされていることもあれば、驚くほどの裏打ちの無さがあることもある。
また、自然言語の意味は、その文脈（コンテキスト）によって定まる部分も多い。これに対して、プログラミング言語は、コンピュータによって扱いやすいように、文脈によって意味が変わることができるだけないように設計されているが、その文脈によって定まる部分がある場合も無くはない。たいていの言語にいくつかはある。
自然言語は、誤用や流行などにより長い時間をかけ、たくさんの人間の利用により、意図せざる形で変化していく。しかし、プログラミング言語の規則は、言語設計者の意図と作業によってのみ、変更される。実際には言語設計者が「たくさんの人間」である場合もあり（仕様が簡単な言語であれば多くの実装者がいることも多く、そういう場合は個々の実装ごとのその仕様があるとも言える）、長い時間をかけ、自然言語と全く同様にたくさんの人間の利用により変化してきたプログラミング言語もある（Lispなど）。また、プログラミング言語にも同様に流行があり、もともとの言語仕様では規定が無かったような一種の「誤用」に、後から仕様が定められる、といったことも必ずしも珍しくはない。
人間がふだん使っている日本語などの自然言語を使ってコンピュータに指示することができるのが理想ではある、と空想する者もいる。しかし、自然言語はあまりにも複雑で曖昧で変則的なので、それを機械語にコンパイルできるようなプログラムを作成することはとても難しい（コンパイルできるできないの問題ではなく、そもそもその意味が「複雑で曖昧で変則的」であること自体が問題なのだが、それを理解できない者が冒頭のように空想するのである）。そのような研究も進められているが、未だに汎用で実用になるプログラムは作成されたことがない。
そこで、自然言語よりも制限が強く、単純で厳密で規則的な人工言語を作って代用する。これがプログラミング言語である。プログラミング言語は自然言語よりもいくらか人間には扱いづらいが、機械語よりは遥かに親しみやすく、人間の指示の手間を軽減している。ちなみにコンピュータ向けの形式性と人間向けの柔軟性を兼ね備えるロジバンなど、本来の開発目的が違えど潜在的に一つのプログラミング言語として機能しうるものもある。
大部分のプログラミング言語は、基本的には概ね文脈自由文法に沿っているが、プログラミング言語における文法的な制限は必ずしも全て文脈自由文法で表現できるとは限らず、文脈自由文法より制限されていることもあれば文脈自由文法より拡張されていることもあり、多くの場合は文脈自由文法には完全には沿っていない。

意味

自然言語の言語学に構文論（統語論）と意味論があるように、そのプログラムが表現しているものは何か、というのが、プログラミング言語の「意味」である。たとえば「a + b という式の値は、aの値とbの値を加算した値である」といったような規則の集まりであり、プログラム意味論という分野で形式的な意味論（形式意味論、formal semantics）も研究されているが、C言語の標準規格など、自然言語で意味を与えている言語や、形式的でない擬似言語のようなもので与えている言語もある。

型システム

型システムは、プログラミング言語において式の値となるデータ型について、型理論にもとづいて分類しどう扱うかを示すものである。
また、内部的には、ディジタルコンピュータでは全てのデータはバイナリ（二進法）で保持される。

型のある言語とない言語

型のある言語は、型システムによって、それぞれの値のデータ型に応じて、定義されていない操作が実行されないよう（多かれ少なかれ）チェックされる機構を持つ。
例えば、"this text between the quotes" は文字列型の値である。ふつう、数を文字列で割る操作には意味がない。そのため、そのようなプログラムは拒絶する。言語によっては、コンパイル時に検出し（静的型検査）コンパイルを失敗とする。言語によっては、実行時に検出し（動的型検査）、例外とするものもあればなんらかのコアーション（型の強制）を行うものもある。（理論的には、静的なシステムのみを指して「型システム」とすることもある）
（型のある言語の特殊例として、単一型言語がある。REXXといったスクリプト言語やSGMLといったマークアップ言語は、単一のデータ型しか扱わない。多くの場合、そのときのデータ型は文字列型である。
アセンブリ言語などの型のない言語は、任意のデータに任意の操作を実行可能であり、データは単にある長さのビット列として扱われる。ある程度高い機能を持ちつつも型が無い（あるいは単一型の）プログラミング言語の例としては、BCPLやForthなどがある（型という概念自体が無いわけではない。例えば「浮動小数点に対する加算」という演算子といったものは存在する。ただしその演算子により、オペランドが何であれそのワードのビットパターンが浮動小数点数を表現しているものとみなされて加算される、といったようなことになる）。
「多かれ少なかれ」と書いたように、「強い」型システムの言語は少なく、多くの言語はそれなりの型システムを採用している。多くの実用的な言語には、型システムを迂回または打倒するような手段が用意されている。

静的型付けと動的型付け

静的型付け（静的型付き言語）では、全ての式の型はそのプログラムを実行する前（一般にコンパイル時）に決定される。例えば、1とか(2+2)という式は整数型であり、文字列を期待している関数には渡せず、日付（型）を格納するよう定義された変数には代入できない。
静的型付けでは、型を明記する場合と型推論を行う場合がある。前者ではプログラマは適切な位置に型を明記しなければならない。後者では、コンパイラが式の型を文脈から推論する。C++やJavaなどの主な静的型付き言語では、型を明記する。完全な型推論は主流でない言語に使われている（HaskellやML）。ただし、型を明記する言語でも部分的な型推論をサポートしていることが多い。たとえば、JavaやC#では限定された状況で型推論を行う。
動的型付け（動的型付き言語）では、型の安全性は実行時に検査される。言い換えれば、型はソース上の式ではなく、実行時の値に対して付与される。型推論言語と同様、動的型付き言語でも式や変数の型を明記する必要はない。また、ある1つの変数がプログラム実行中に異なる型の値を格納することも可能である。しかし、コードを実際に実行してみるまで型の間違いを自動的に検出することができず、デバッグがやや難しい。動的型付き言語としては、Ruby、LISP、JavaScript、Pythonなどがある。

実行意味論

データを入力されれば、コンピュータはそのデータに対して何らかの処理を実行する。「実行意味論(execution semantics)」とは、プログラミング言語の構成要素がどの時点でどのようにして、そのプログラムの振る舞いを生成するのかを定義するものである。
例えば、式の評価戦略（先行評価、部分評価、遅延評価、短絡評価など）は実行意味論の一部である。また、制御構造における条件付実行の作法も実行意味論の一部である。

標準ライブラリ

「ライブラリ」は、プログラムを書いたり使用する上での、補助的なルーチン群である。多くのプログラミング言語には、言語仕様の一部、あるいは言語本体の仕様とは独立していることもあるが、標準ライブラリの仕様もほぼ必ず存在し、その言語の実装には標準ライブラリの実装もほぼ必ず付属する。標準ライブラリには、典型的なアルゴリズム、データ構造、入出力機構などが含まれることが多い。
ユーザーから見れば、標準ライブラリも言語の一部だが、設計者から見れば別の実体である。言語仕様には必ず実装しなければならない部分が定義されており、標準化された言語の場合、それには標準ライブラリも含まれる。言語とその標準ライブラリの境界は、言語によって様々である。実際、言語によっては一部の言語機能が標準ライブラリなしでは使えないこともある（たとえば累乗の演算子がある言語があるが、それのコンパイル結果はその言語の多くの処理系で関数呼出であろう。それが、言語仕様として標準ライブラリの該当する関数を呼び出すよう決められているような場合は「一部の言語機能が標準ライブラリなしでは使えない」ということになる）。
マクロもライブラリに含まれることも多い。たとえばC言語の標準には、いくつかの名前が関数ではなくマクロで提供されるかもしれない、といったような規定などがある。またLisp系の言語では、いわゆる特殊形式の多くが言語組込ではなくマクロでも実装可能であり、ifとcondのようにどちらか片方は必要だが、片方があればもう片方はマクロにできる、といったようなものもある。Schemeの標準規格は、どれを言語組込とし、どれをマクロとするか、ほとんどを処理系実装者の自由に任せている。

設計と実装

コンピュータ・プログラミング言語の設計は「言語仕様」として示され、実装は「言語処理系」と呼ばれる。以下はそれらについての概観である。

仕様

前述のようにプログラミング言語は構文と意味から成るから、仕様についても、構文仕様と意味仕様がある。

構文仕様

構文仕様は一般にバッカス・ナウア記法などによって形式的に示される。

意味仕様

意味論の仕様は、自然言語などで記述されることが多いが、形式的に与えられている言語もある。
形式意味論（プログラム意味論の記事も参照）で意味論を記述した例として Standard ML や Scheme がある。

処理系

プログラミング言語の実装は、プログラミング言語処理系と呼ばれる。コンパイラは、ソースコードなどの入力を中間表現などの、より解釈実行しやすい表現に変換する処理系である。また、インタプリタは、入力されたプログラムを解釈実行する処理系である（ハードウェアのプロセッサは、機械語を解釈実行するインタプリタである、と見ることができる）。
コンパイラとインタプリタの関係は、理論的には二村射影により美しく定式化されている。
なお、「大きく分けて2つの方法がある。コンパイラとインタプリタである。一般にある言語をコンパイラとインタプリタの両方で実装することが可能である。」などといったように（従来書かれた通俗的解説書などには大変多いが）理解していると、Javaなど近年の多くの言語処理系のスタイルが全くわからない、ということになる。
（機械語にまで変換するもののみを指してコンパイラと呼びたがる向きが一部にあり、その立場にもある程度は理もあるのだが、そうするとJavaの一般的な実装を指す用語が無くなる）
「コンパイラの出力したものをインタプリタで実行する方式は、コンパイラとインタプリタの区別が曖昧な場合もある。」などという変な説明をする者もいるが、前述したように、そもそも間違った2分法で考えているから、そのような変な考え方になるのである。
一般に、機械語に変換したもの（実行ファイル）を直接ハードウェアで実行する方が、インタプリタで実行するよりもずっと高速である。インタプリタでの実行を改善する技法として、実行時コンパイラなどの動的コンパイル手法がある。

意義と目的

（コンピュータ）プログラミング言語は、おもに英語の単語と記号を組み合わせた（英語である必然性はひと欠片も無いが）、特殊な文法（正確には「構文」。誰にとって特殊かは不明だが）で記述される。その意義は、人とコンピュータの意思疎通を容易にするため、数字の羅列に代えて人間に扱いやすい言語形式を提供することにある。プログラミング言語があれば、人は扱いやすく理解できる言葉でコンピュータへの指示を書くことができる。プログラミング言語で書かれたコードは、アセンブラ、コンパイラ、インタプリタなど「プログラミング言語処理系」と呼ばれるプログラムによって処理（機械語あるいは中間表現に変換されたり、解釈実行されたり）される。
プログラミング言語は、コンピュータ企業や技術者により目的に応じて開発され、様々なプログラミング言語が、毎年のように生み出されている。2008年2月時点で、「コンピュータ言語辞典」には8152種のプログラミング言語が記載されていた。

初期の発展

「コンピュータ」（という語）の定義次第ではあるが、それを「コンピュータ・プログラムによって駆動される機械」とするならば、コンピュータ・プログラムはコンピュータとともに生まれ、育ったということになり、そのプログラムの記法としてプログラミング言語があった、ということになる。チャールズ・バベッジが階差機関に続いて計画した解析機関は、パンチカードの先祖と言えるような穴の開いた厚紙の列によって制御されるという機構を持っていたため、その特徴から「19世紀のコンピュータ」「蒸気動力のコンピュータ」などと呼ばれることがある。
20世紀初頭には、タビュレーティングマシンによってパンチカードを使ったデータの機械処理が始まっている。そういった実際面ばかりではなく計算理論としても、1930年代から1940年代にかけて、アルゴリズムを表現する数学的抽象表現を提供するラムダ計算（アロンゾ・チャーチ）とチューリングマシン（アラン・チューリング）が考案された。ラムダ計算はその後の言語設計にも影響を与えている。
1940年代、世界初の電子式デジタルコンピュータ群が製作された。1950年代初期のコンピュータであるUNIVAC IやIBM 701では機械語を使っていた。機械語によるプログラミングは、間もなくアセンブリ言語によるプログラミングに取って代わられた。1950年代後半になると、アセンブリ言語でマクロ命令が使われるようになり、その後 FORTRAN、LISP、COBOLという3つの高水準言語が開発された。これらは改良を加えられ現在でも使われており、その後の言語開発に重大な影響を与えた。1950年代末、ALGOLが登場し、その後の言語に様々な影響を与えている。初期のプログラミング言語の仕様と使い方は、当時のプログラミング環境の制約（パンチカードによるプログラム入力など）にも大きく影響されている。

統合と成長

1980年代は、相対的な統合の時代であった。C++は、オブジェクト指向とシステムプログラミングの統合である。アメリカでは、軍需に使うことを目的としてAdaというシステムプログラミング言語が標準化された。日本などでは、論理プログラミングを応用した第五世代言語の研究に資源を費やした。関数型言語コミュニティではMLとLISPの標準化の動きがあった。これらはいずれも新たなパラダイムを生み出そうというものではなく、それまでに生み出されたアイデアに改良を加える動きであった。
1980年代の重要な言語設計傾向の1つとして、大規模システムのためのプログラミングを目的としてモジュールの概念を採り入れた点が挙げられる。1980年代にモジュールシステムを採り入れた言語として、Modula-2、Ada、MLがあるが、それ以前には、既にPL/Iがモジュラープログラミングをサポートしていた。モジュールシステムはジェネリックプログラミングの構成要素とされることが多い。
1990年代中頃には、インターネットの急激な成長によって新たな言語が生み出される機会が生じた。Perlは1987年にリリースされたUNIX上のスクリプト言語だったが、ウェブサイトの動的コンテンツ作成に使われるようになった。Javaはサーバ側のプログラミングに使われるようになった。

分類

プログラミング言語の完全な分類法は存在しない（前述の、COBOLは事務計算用途向け、FORTRANが科学技術計算用途向けといったような、ある程度の方向性はあるが）。あるプログラミング言語には大抵複数の起源（影響を与えた言語）がある。言語は一般に複数の既存言語の要素と新たなアイデアを組み合わせて生み出される。ある言語を起源とするアイデアはその系統の言語群に広まっていき、あるときギャップを飛び越えて全く別の系統の言語で使われるようになる。
さらに事を複雑にするのは、言語は様々な観点から分類可能という点である。例えば、Javaはオブジェクト指向言語であると同時に、並行性言語でもある（言語仕様としてスレッドを複数並行して生成可能であるため）。Pythonはオブジェクト指向言語であると同時に、スクリプト言語でもある。
プログラミング言語の大まかな分類として、プログラミングパラダイムによる分類と想定している利用分野や用途による分類がある。パラダイムには、手続き型プログラミング、オブジェクト指向プログラミング、関数型プログラミング、論理プログラミングなどがある。言語によっては2つのパラダイムの性格を併せ持つこともあるし、マルチパラダイムの場合もある。アセンブリ言語は、マシンのアーキテクチャを直接モデル化したものであるため、パラダイムとは言わない。用途による分類では、汎用、システムプログラミング言語、スクリプト言語、ドメイン固有言語、並行/分散言語（あるいはこれらの混合）などがある。汎用言語の一部は教育目的で設計されている。
プログラミングパラダイムとは無関係なパラメータで分類されることもある。例えば、多くのプログラミング言語は英語のキーワードを使っているが、ごく一部の言語はそうではない。また、難解かそうでないかという分類もある。

低水準言語と高水準言語

機械語やアセンブラ言語は、よりハードウェアに近い言語であり、このようなプログラミング言語を低水準言語という。また、それ以外の言語は、機械語と一対一で対応せず、より人間に近い言語であり、高水準言語という。