コンピュータ科学において、拡張可能なプログラミングとは、プログラミング言語、コンパイラ、およびランタイムシステム(環境)を拡張するメカニズムに焦点を当てたコンピュータプログラミングのスタイルです。このスタイルのプログラミングをサポートする拡張可能なプログラミング言語は、1960年代には活発な研究分野でしたが、1970年代にはその動きは衰退しました。[ 1 ]拡張可能なプログラミングは、21世紀に入って再び注目を集めるトピックとなっています。[ 2 ]
拡張可能なプログラミング言語運動と関連付けられる最初の論文は、通常[ 1 ] [ 3 ]、 M.ダグラス・マキルロイの 1960 年の論文「高水準プログラミング言語のマクロについて」である。[ 4 ]拡張性の原理に関するもう 1 つの初期の記述は、ブルッカーとモリスの 1960 年の論文「コンパイラ コンパイラについて」にある。[ 5 ]この運動のピークは、1969 年と 1971 年の 2 つの学術シンポジウムによって特徴づけられた。[ 6 ] [ 7 ] 1975 年までに、トーマス A. スタンディッシュによるこの運動に関する調査記事[ 1 ]は、実質的に事後検証であった。フォースは例外であったが、それは実質的に注目されなかった。
一般的に想定されている拡張可能な言語は、基本的な計算機能を提供する基本言語と、その基本言語を変更できるメタ言語から構成される。そしてプログラムは、メタ言語による変更と、変更された基本言語で記述されたコードから構成される。
この運動で最も顕著な言語拡張技術はマクロ定義でした。文法修正もこの運動と密接に関連しており、最終的に適応文法形式の開発につながりました。Lisp言語コミュニティは拡張可能な言語コミュニティとは別個のままでしたが、ある研究者が指摘したように、
プログラムとデータが本質的に交換可能なプログラミング言語は、拡張可能な言語とみなすことができる。…これは、Lispが長年にわたって拡張可能な言語として使用されてきたという事実から容易に理解できる。[ 8 ]
1969年の会議で、Simulaは拡張可能な言語として発表された。
スタンディッシュは言語拡張の3つのクラスを説明し、それらを言い換え、正式表現、メタ表現と名付けた(言い換えとメタ表現は翻訳用語である)。
スタンディッシュは、拡張性運動の失敗の原因を、連続的な拡張のプログラミングの難しさにあるとした。プログラマーは、基本言語を基盤としてマクロの最初のシェルを構築するかもしれない。次に、そのシェルを基盤として2番目のシェルを構築する場合、後続のプログラマーは基本言語と最初のシェルの両方に精通していなければならない。3番目のシェルを構築するには、基本言語と最初のシェル、2番目のシェルの両方に精通している必要があり、以下同様である。プログラマーを低レベルの詳細から保護することが、拡張性運動に取って代わった抽象化運動の意図である。
Simula は以前は拡張可能であると説明されていたにもかかわらず、1975 年までに Standish の調査には実際には新しい抽象化ベースのテクノロジーが含まれていなかったようです (ただし、彼は技術的にはそれらを含めることができたであろう拡張性の非常に一般的な定義を使用していました)。コンピュータの発明からそれまでの 1978 年のプログラミング抽象化の歴史では、マクロについて言及されておらず、拡張可能な言語運動が起こったことを示唆するものもありませんでした。[ 9 ]マクロは、構文抽象化という仮名を与えられ、1980 年代後半までに (おそらく衛生的なマクロの出現により)暫定的に抽象化運動に受け入れられました。[ 10 ]
現代的な意味では、拡張可能なプログラミングをサポートするシステムは、以下に説明するすべての機能を提供する。
これは、コンパイル対象のソース言語が閉じた、固定された、または静的であってはならないことを意味します。ソース言語に新しいキーワード、概念、および構造を追加できる必要があります。ユーザー定義構文で構造を追加できる言語には、Rocq、[ 11 ] Racket、Camlp4、OpenC++、Seed7、[ 12 ] Red、Rebol、およびFelixなどがあります。基本的な言語機能や固有の機能が不変であることは許容されますが、システムはそれらの言語機能だけに依存すべきではありません。新しい機能を追加できる必要があります。
拡張可能なプログラミングにおいて、コンパイラはソースコード入力をバイナリ実行可能出力に変換する単一のプログラムではありません。コンパイラ自体は拡張可能でなければならず、ソース言語入力をあらゆる形式に変換するのを支援するプラグインの集合体である必要があります。例えば、拡張可能なコンパイラは、オブジェクトコード、コードドキュメント、再フォーマットされたソースコード、またはその他の必要な出力の生成をサポートします。コンパイラのアーキテクチャは、ユーザーがコンパイルプロセスに「介入」し、コンパイルプロセスのあらゆる適切な段階で代替処理タスクを提供できるようにする必要があります。
ソースコードをコンピュータ上で実行可能な形式に変換するという作業のためだけに、拡張可能なコンパイラは以下の機能を備えているべきである。
実行時において、拡張可能なプログラミングシステムは、言語が許容する操作セットを拡張できるようにする必要があります。例えば、システムがバイトコードインタープリタを使用する場合、新しいバイトコード値を定義できるようにする必要があります。拡張可能な構文と同様に、不変の基本操作または固有の操作が(比較的小規模な)セットとして存在することは許容されます。ただし、新しい動作や追加の動作をサポートできるように、それらの固有の操作をオーバーロードまたは拡張できる必要があります。
拡張可能なプログラミングシステムは、プログラムを処理対象データとして扱うべきである。これらのプログラムには、いかなる種類の書式情報も含まれてはならない。ユーザーへのプログラムの視覚的な表示と編集は、拡張可能なコンパイラによってサポートされる翻訳機能であるべきであり、プログラムデータを、表示や編集に適した形式に変換する。当然ながら、これは双方向の翻訳であるべきである。これは、拡張可能なプログラムを様々な方法で容易に処理できるようにする必要があるため重要である。ソース言語入力の用途が編集、表示、機械語への変換のみであることは容認できない。ソース入力を、その処理方法(書式設定、保存、表示、編集など)の仕様から切り離すことで、プログラムの任意の処理が容易になる。
拡張可能なプログラミングシステムは、プログラムが実行可能となるためにどのような拡張や変換を受けているかに関わらず、元のソース言語の構造を使用してプログラムのデバッグをサポートする必要があります。特に、実行時データを表示する唯一の方法が構造体や配列であると想定することはできません。デバッガ、より正確には「プログラムインスペクタ」は、ソース言語に適した形式で実行時データを表示できるようにする必要があります。たとえば、言語がビジネスプロセスやワークフローのデータ構造をサポートしている場合、デバッガはそのデータ構造をフィッシュボーン図やプラグインによって提供されるその他の形式で表示できる必要があります。