コンパイラ

概説

プログラミング言語（人間が理解しやすい言語や数式でプログラムを記述可能な人工言語）で書かれたプログラムを、コンピュータのプロセッサが直接的に実行できる機械語（バイナリコード）、あるいは元のプログラムよりも低いレベルのコード（例えばバイトコードなどの仮想機械向け中間言語あるいは中間表現）に変換することを、英語の動詞で"compile"（コンパイル）と呼ぶ。コンパイラとは、コンパイルを行なうコンピュータプログラムのことである。
コンパイラによって変換される前のプログラムを「ソースコード」と呼び、変換後の機械語あるいは中間言語のプログラムなどを「オブジェクトコード」と呼ぶ。なお、開発環境や処理系によっては、変換することを"build"（ビルド）と呼んでいるものもある。ただし、厳密には「コンパイル」は「ビルド」の一工程である。直接バイナリコードを出力するものもあるが、コンパイラ自体はアセンブリ言語によるコードを出力するにとどまり、その先、それをバイナリに変換する作業（アセンブル）はアセンブラに任せているものも多い。
「compile」はもともと「編集する」「編纂する」という意味の英語であり、「compiler」というのは「編集者」という意味の英語である。なお、日本語による解説書などには「コンパイラー(compiler)という名称は日本語では、翻訳者という意味を持ち、ソフトウェアとしてのコンパイラーは翻訳機という意味を持っている」などという解説がよくある。
近年のコンパイラでは、ひとつのプログラムとして動作する全てのコードをいっぺんにコンパイルするのではなく、モジュール毎などに分けてコンパイルし（「分割コンパイル」）、ライブラリなどはあらかじめコンパイルされているものと合わせて、実行するようにすることが多い。この場合、コンパイラはリロケータブルバイナリを出力し、実行可能ファイルの生成にはリンケージエディタが必要であり、さらに動的リンクで実行する場合はダイナミックリンカ／ローダ（ローダの一種）も必要である。
近年の開発環境などでは、コンパイル（ビルド）して実行、というような手続きを1命令で行えるものも増えている。そして、インタプリタでも実行時コンパイラなどの技術の利用がさかんになってきており、古典的な意味での「コンパイラ」と「インタプリタ」の中間的な性質のツール（プログラム）も増えてきているので、「コンパイラ言語 / インタプリタ言語」という、以前よく行われた対比は、あまり意味を持たない場合も増えてきている。

歴史

初期のコンピュータのプログラミングは機械語で直接行なわれていた。プログラムを指して「コード」（暗号の意がある）と呼ぶのは、知らない人間には機械語は全く意味のわからない数値の羅列だからである。しかし、（人間にとって比較的理解のしやすい）十進法の数字で書かれたアドレスを内部表現の二進法に変換する、といったごく単純なアセンブリ言語の機能を持ったプログラムはEDSACにおいて既に存在していた。
機械語でのプログラミングは言うに及ばず、アセンブリ言語を用いても、プログラミングというのは面倒な作業である。そういった低水準言語から、人間がより扱いやすい高水準言語が徐々に求められるようになった。また、機械の詳細が抽象化されることにより、高水準なプログラミング言語で書かれた同一のソースコードを元に、詳細仕様が異なる機械でも動くプログラムを生成できる、という利点もあった。
1950年代末までに、プログラミング言語がいくつか提案され、実験的なコンパイラがいくつか開発された。世界初のコンパイラは、1952年にグレース・ホッパーが書いたA-0 Systemだとされることもある。ただし一般的には、1957年にIBMのジョン・バッカスのチームが開発したFORTRANコンパイラが世界初の完全なコンパイラであるとされている。一般的なコンパイラの開発では、まず動くものを作ってから最適化の機能を付加するが、最初のFORTRANコンパイラでは、コンパイラが実用になることを示すために、最初から最適化に労力が向けられた。
1960年の、ホッパーらによるCOBOLは複数のアーキテクチャ上でコンパイル可能となった言語の最初期の1つである。
様々なアプリケーション領域で、高水準言語というアイデアは素早く浸透していった。機能が拡張されたプログラミング言語が次々と提案され、コンピュータのアーキテクチャそのものも複雑化していったため、コンパイラはどんどん複雑化していった。
初期のコンパイラはアセンブリ言語で書かれていた。世界初の「セルフホスティングコンパイラ」（＝コンパイル対象言語で書かれたコンパイラのソースコードをコンパイルできるコンパイラ）は、1962年にマサチューセッツ工科大学の Hart と Levin が開発したLISPである。1970年代には、特にPascalやC言語などにおいて、コンパイル対象言語でコンパイラを書くことが一般化した。さらにより高水準の言語のコンパイラは、PascalやC言語で実装することも多い。セルフホスティング・コンパイラの構築には、ブートストラップ問題がつきまとう。すなわち、コンパイル対象言語で書かれたコンパイラを最初にコンパイルするには、別の言語で書かれたコンパイラが必要になるという問題である。Hart と Levin の LISPコンパイラではコンパイラをインタプリタ上で動作させてコンパイルを行なった。

分類

機械語にコンパイルするコンパイラもあれば、そうでないコンパイラ（後述）もある。機械語コードのことを、ハードウェアであるプロセッサの生のコード、というような意味でネイティブコードなどと言うことがあり、機械語にコンパイルするコンパイラのことをネイティブコンパイラと言うことがある。
コンパイラに限らず、入力と出力を持つあらゆる変換系は、入力の種類がm種類、出力の種類がn種類あるとすると、m×n種類があることになる。コンパイラの場合、プログラミング言語がm種類、コード生成の対象となる命令セットアーキテクチャがn種類、といったような感じになるわけであり、入力側をフロントエンド、出力側をバックエンドと言うが、中間表現の設計いかんでは、残りの中間処理の部分、特に重要な部分であるコンパイラ最適化を共有できるため、1980年代以降に基本設計が為されたGCCやCOINSやLLVMなどでは、そのようにして多言語・多ターゲットに対応している。
汎用OSなど、開発環境と同じ環境で目的プログラムも動作させるような開発を「セルフ開発」と言い、セルフ開発のコンパイラを「セルフコンパイラ」という。それに対し、開発環境とは別の環境で実行するような開発を「クロス開発」といい、そのためのコンパイラを「クロスコンパイラ」という。OSカーネル自身のコンパイルなどは、カーネル自身の実行環境は、そのOSではなくベアメタルであるという意味ではある種のクロスコンパイルのようなものであるし、新しいコンピュータシステムのための環境を最初に作るにはクロス開発の必要がある。あるいは、組み込みシステムやPDAなど、それ自体が開発環境を動作させるだけの機能and・or性能を持たない場合、といったものもある。
いわゆるネイティブコードではなく中間コードを生成し、さらに別のコンパイラに処理を任せたり、別のインタプリタによって実行したりするものもある。これを中間コードコンパイラ、（バイトコードと呼んでいる場合は）バイトコードコンパイラなどと呼ぶ。またそのバイトコードを解釈実行する処理系をバイトコードインタプリタなどと呼ぶ。

コンパイラ言語

もっぱらその言語の処理系がコンパイラとして実装される言語を「コンパイラ言語」などと言い、インタプリタとして実装される言語を「インタプリタ言語」などと言うこともあるが、実験的な実装まで含めればどちらもある言語も多い。Microsoft Visual Studioに付属するF#/C# Interactiveのように、対話環境 (REPL) で入力したプログラムを、コンパイラで共通中間言語（中間表現）にコンパイルし、さらに共通言語ランタイム（仮想機械）上でネイティブコードにJITコンパイルしてインタプリタ的に実行する、というような処理系もある。JavaやMicrosoft Visual Basicのように、登場当初はインタプリタ方式だったが、のちにネイティブコードへのJITコンパイルやAOTコンパイルをサポートするようになった言語もある。
言語によっては、仕様にコンパイラの存在を前提とした項目があるものもある（たとえばCommon Lisp）。また、インタプリタの実装が容易でコンパイラの実装が困難な言語もある（APL、SNOBOL4など）。メタプログラミングの利用、特に文字列をevalすることは、インタプリタ方式では造作ないことだが、コンパイラ方式では実行環境にコンパイラ自体が必要となる（動的プログラミング言語も参照）。

ハードウェア・コンパイラ

ハードウェア記述言語の処理系（合成系）を、ハードウェアコンパイラとかシリコンコンパイラなどと呼ぶことがある。