プログラミング言語は通常、コンピュータプログラムの表現形式を設計し、開発された概念の実装を記述することによって作成されます。[ 1 ]通常はインタプリタまたはコンパイラです。インタプリタは、通常はテキスト形式のプログラムを読み取り、読み取った内容に基づいてアクションを実行するように設計されています。一方、コンパイラはコードをオブジェクトコードなどの低レベルの形式に変換します。[ 2 ]
デザイン
プログラミング言語の設計には、考慮すべき要素が多岐にわたります。中には互いに排他的な要素もあります(例:セキュリティと速度)。プログラミング言語のパフォーマンスがインタープリタ型とコンパイル型のどちらに優れているか、言語を動的型付けと静的型付けのどちらにすべきか、継承の有無、言語の一般的な構文などを考慮する必要があるかもしれません。[ 3 ]言語の設計に関わる多くの要素は、その言語の背後にある目標によって決まります。言語の対象読者、言語独自の機能、目的を考慮することが重要です。[ 4 ]言語が目的を果たすかどうかを確認するには、既存の言語に何が欠けているか、何が困難になっているかを確認することをお勧めします。[ 4 ]
さまざまな専門家が、役立つ設計原則を提案しています。
- 1972年に発表された記事の最後の段落で、トニー・ホーアはあらゆるソフトウェアプロジェクトに対する一般的なアドバイスを提供しています。[ 5 ]
- 未来のソフトウェアの設計者や実装者への私のアドバイスは、一言で言えば次のようになります。「やり方が分かるまでは、何をするかを正確に決めてはいけない。そして、品質に関するすべての基準に照らして計画を評価するまでは、どのようにするかを決めてはいけない。それができないなら、できるまで設計を簡素化しなさい。」
- 1973年のSIGPLANシンポジウムで、トニー・ホーアは言語の様々な側面について詳しく議論しました。[ 6 ]彼はまた、当時のプログラミング言語のいくつかの欠点を指摘しています。
- 「プログラミング言語は、プログラマーの最も難しい側面、つまりプログラムの設計、ドキュメント作成、デバッグを支援するツールです。」
- 「優れた言語設計の客観的な基準は、シンプルさ、セキュリティ、高速な翻訳、効率的なオブジェクト コード、読みやすさという 5 つのキャッチフレーズに要約できます。」
- 結果に全く信頼を置いていないデバッグ実行時に、入念なセキュリティチェックを実施しておきながら、誤った結果が大きな損失や悲惨な結果をもたらす可能性がある本番実行時に、そのチェックを外すというのは、全くもって不合理です。陸上での訓練ではライフジャケットを着用しているのに、海に出るとすぐに脱ぐセーリング愛好家を、私たちはどう思うでしょうか?
- 1974年のIFIP会議で、パスカルの設計者であるニクラウス・ヴィルトは「プログラミング言語の設計について」と題する論文を発表しました。[ 7 ]ヴィルトはいくつかの競合する提案を挙げましたが、中でも特に注目すべきは、言語は学習と使用が容易であること、新機能を追加しなくても使用可能であること、コンパイラは効率的なコードを生成すること、コンパイラは高速であること、そして、言語はライブラリ、その言語が実行されるシステム、そして他の言語で書かれたプログラムと互換性があることでした。
多くのプログラミング言語には、少なくとも最初のバージョンのコンパイラやインタープリタの実装を容易にするための設計上の特徴があります。例えば、Pascal、Forth、そして多くのアセンブリ言語は、ワンパスコンパイルをサポートするように特別に設計されています。
新しいプログラミング言語は、多くの場合、以前のプログラミング言語の(認識されていた)問題を修正するために設計されており、通常は(インタプリタやコンパイラは複雑になるかもしれませんが)その言語で書かれたプログラムをよりシンプルにする機能を追加することで対応しています。例えば、自動メモリ管理とガベージコレクションが組み込まれた言語、連想配列が組み込まれた言語などが挙げられます。
一方、BCPL、Pascal、RPythonなど、コンパイルを困難にする機能を意図的に省くことで、セルフホスティング コンパイラを比較的簡単に作成できるように特別に設計されたプログラミング言語もいくつかあります。
実装
プログラミング言語の実装には一般的に2つのアプローチがある: [ 8 ]
- 解釈:プログラムはインタープリタによって入力として読み込まれ、インタープリタはプログラムに書かれた動作を実行します。 [ 9 ]
- コンパイル:プログラムはコンパイラによって読み込まれ、バイトコードや機械語などの他の言語に変換されます。変換されたコードは、ハードウェアによって直接実行されるか、別のインタープリタやコンパイラへの入力として使用されます。 [ 9 ]
これら 2 つの極端な例に加えて、多くの実装では、ジャストインタイム コンパイルやバイトコード インタープリターなどのハイブリッド アプローチが使用されます。
インタプリタはJITコンパイラや事前コンパイラに比べていくつかの利点がある。[ 10 ] 通常、インタプリタは読み取り-評価-印刷ループをサポートしており、これにより新しいプログラムの開発が大幅に高速化される。一方、コンパイラは開発者に、はるかに遅い編集-コンパイル-実行-デバッグループの使用を強制する。
典型的なプログラムは、事前コンパイラでコンパイルされると、(コンパイル後に)同じプログラムをJITコンパイラで処理して実行した場合よりも高速に実行されます。JITコンパイラで処理して実行した場合、同じプログラムをバイトコードなどのpコード中間言語に部分的にコンパイルしてアプリケーション仮想マシンで解釈した場合よりも高速に実行される可能性があります。アプリケーション仮想マシンは、純粋なインタープリタよりもはるかに高速に実行されます。[ 11 ]
理論的には、プログラミング言語はまず仕様を定め、その後にインタプリタやコンパイラを実装することができます(ウォーターフォールモデル)。実際には、言語の実装中に得られた知見が、後のバージョンの言語仕様に影響を与えることが多く、プログラミング言語の設計と実装が一体化されることになります。
通常、インタープリタとコンパイラはどちらも何らかのシンボル テーブルを実装します。
通訳者
インタプリタは、他のプログラムを通常はテキストとして読み込むプログラムです。 [ 4 ] Pythonなどの言語に見られます。[ 2 ]インタプリタはコードを読み取り、結果を直接生成します。[ 12 ]インタプリタは通常、コードを1行ずつ読み取り、解析してコードを操作やアクションに変換して実行します。[ 13 ]
インタプリタは、パーサと評価器という2つの部分から構成されます。プログラムはインタプリタによって入力として読み込まれると、パーサによって処理されます。パーサはプログラムを言語構成要素に分解し、構文木を形成します。評価器は構文木を用いてプログラムを実行します。[ 14 ]
仮想マシン
仮想マシンは、バイトコードを解釈する特殊なタイプのインタープリタです。[ 9 ]バイトコードはマシンコードに似た移植可能な低レベルコードですが、通常は物理マシンではなく仮想マシン上で実行されます。[ 15 ]効率性を向上させるために、Java [ 15 ] 、Python [ 16 ]、C# [ 17 ]などの多くのプログラミング言語は、解釈される前にバイトコードにコンパイルされます。
ジャストインタイムコンパイラ
一部の仮想マシンには、バイトコード実行の効率を向上させるためのジャストインタイム(JIT)コンパイラが搭載されています。仮想マシンによるバイトコード実行中に、JITコンパイラはバイトコードの一部が繰り返し使用されると判断した場合、その部分をマシンコードにコンパイルします。その後、JITコンパイラはマシンコードをメモリに保存し、仮想マシンで使用できるようにします。JITコンパイラは、コンパイル時間の延長と実行時間の短縮のバランスを取ろうとします。[ 9 ]
コンパイラ
コンパイラは、ある言語で書かれたプログラムを別の言語に翻訳します。ほとんどのコンパイラは、フロントエンド、オプティマイザ、バックエンドの3つの段階で構成されています。フロントエンドはプログラムを理解する役割を担います。プログラムが有効であることを確認し、それを中間表現(コンパイラがプログラムを表現するために使用するデータ構造)に変換します。オプティマイザは中間表現を改善することで、コンパイラが最終的に生成する実行ファイルの速度を向上させたり、サイズを縮小したりします。バックエンドは、最適化された中間表現をコンパイラの出力言語に変換します。[ 18 ]
ある高水準言語のコンパイラが別の高水準言語を生成する場合、それはトランスパイラと呼ばれます。トランスパイラは、既存の言語を拡張したり、他の言語( C言語など)の移植性が高く最適化された実装を利用することでコンパイラ開発を簡素化したりするために使用できます。[ 9 ]
解釈とコンパイルには様々な組み合わせが可能であり、多くの現代的なプログラミング言語の実装には両方の要素が含まれています。例えば、Smalltalkプログラミング言語は、従来、バイトコードへのコンパイルによって実装され、その後、仮想マシンによって解釈またはコンパイルされます。Smalltalkバイトコードは仮想マシン上で実行されるため、異なるハードウェアプラットフォーム間で移植可能です。[ 19 ]
複数の実装
プログラミング言語には複数の実装が存在する場合があります。異なる実装は異なる言語で記述され、異なる方法でコードをコンパイルまたは解釈することができます。例えば、Pythonの実装には以下が含まれます。[ 20 ]
- CPython、Pythonのリファレンス実装
- IronPython 、 .NET Frameworkを対象とした実装( C#で記述)
- Jython 、 Java仮想マシンをターゲットとした実装
- PyPy、速度を重視して設計された実装(RPythonで記述)
プロセス
プログラミング言語を作成するプロセスは開発者によって異なる場合がありますが、共通の概念を含むプログラミング言語を作成する一般的なプロセスは次のとおりです。
- 設計:言語を開発する際には、型、構文、意味、ライブラリの使用などの設計面が考慮されます。[ 21 ]
- 考慮点:構文、実装、その他の要素が考慮されます。Pythonのような言語は実行時にコードを解釈しますが、C++のような言語はCのコンパイラをベースにコンパイラを構築するというアプローチを採用しています。 [ 22 ]
- 実装の作成:最初の実装が記述されます。コンパイラは他の形式に変換しますが、通常はアセンブリ言語のような低レベル言語、さらにはバイナリ言語にまで変換されます。[ 23 ]
- 実装の改善:実装は改善されるべきです。プログラミング言語を拡張し、ブートストラップに必要な機能を備え、プログラミング言語が自ら実装を記述できるレベルを目指しましょう。
- ブートストラッピング: コンパイラを使用する場合、開発者はブートストラッピングというプロセスを使用する場合があります。これは、プログラミング言語のコンパイラ自体を書き換えるものです。[ 24 ]これはバグチェックや機能の証明に適しています。[ 25 ]ブートストラッピングには、その後は言語自体をプログラムするだけで済むという利点もあります。
参考文献
- ^ Tomassetti, Federico (2019年5月8日). 「プログラミング言語を作成するにはどうすればいいでしょうか?」 . Strumenta . 2023年3月3日閲覧。
- ^ a b「コンパイラ vs インタープリタ」 . Geeks For Geeks . 2022年1月17日. 2023年3月3日閲覧。
- ^ 「プログラミング言語と学習」ワシントンEDUワシントン大学。 2023年3月2日閲覧。
- ^ a b c「プログラミング言語はどのように作られるのか」 GoNoCode . 2021年12月8日. 2023年3月2日閲覧。
- ^ Hoare, CAR (1972). 「ソフトウェアの品質」 .ソフトウェア:実践と経験. 2 (2): 103– 105. doi : 10.1002/spe.4380020202 . S2CID 62662609 .
- ^ 「プログラミング言語設計のヒント」(PDF) 1973年. 2023年3月7日閲覧。
- ^ 「プログラミング言語の設計について」(PDF) 1974年. 2023年3月9日閲覧。
- ^ Ranta, Aarne (2012年2月6日).プログラミング言語の実装(PDF) . College Publications. pp. 16– 18. ISBN 9781848900646. 2020年11月7日時点のオリジナルよりアーカイブ(PDF) . 2020年3月22日閲覧。
- ^ a b c d e Baker, Greg. 「言語実装」 .サイモンフレーザー大学コンピューティングサイエンス. 2019年3月8日時点のオリジナルよりアーカイブ。 2020年3月22日閲覧。
- ^ KernelTrap. 「ジャストインタイムコンパイルに代わる、より効率的なバイトコードインタープリタ」。
- ^ ラリー・フィッシュ。 「Apex/XPL0と6502グループの裏話」。
- ^ Diver, Laurence (2021年12月7日). 「2021年12月7日発行 コードのルールの解釈:パフォーマンス、パフォーマティビティ、そしてプロダクション」 MIT計算法レポート.
- ^ Rathi, Mukul (2017年3月31日). 「私が独自の「適切な」プログラミング言語を書いた方法」 . mukulrathi . 2023年3月2日閲覧。
- ^ Evans, David (2011年8月19日).コンピューティング入門(PDF) . バージニア大学. p. 211. 2020年3月22日閲覧。
- ^ a b Sridhar, Jay (2017年8月29日). 「Java仮想マシンがコードの実行速度を向上させる理由」 . MakeUseOf . 2020年3月22日閲覧。
- ^ Bennett, James (2018年4月23日). 「Pythonバイトコード入門」 . Opensource.com . 2020年3月22日閲覧。
- ^ Ali, Mirza Farrukh (2017年10月12日). 「Common Language Runtime(CLR) DotNet」 . Medium . 2020年3月22日閲覧。
- ^クーパー、キース、トルゾン、リンダ(2011年2月7日)『コンパイラのエンジニアリング』(第2版)モーガン・カウフマン、 6-9頁。ISBN 9780120884780。
- ^ルイス、サイモン(1995年5月11日)『スモールトークの芸術と科学』(PDF)プレンティス・ホール、 20~ 21頁。ISBN 9780133713459. 2020年3月23日閲覧。
- ^ 「代替Python実装」 . Python.org . 2020年3月23日閲覧。
- ^ Chouchanian, Vic. 「プログラミング言語」カリフォルニア州立大学ノースリッジ校. 2023年3月2日閲覧。
- ^ Stroustrup, Bjarne. 「C++の歴史:1979−1991」(PDF) . 2019年2月2日時点のオリジナルよりアーカイブ(PDF) 。 2013年7月18日閲覧。
- ^ Ferguson, Andrew. 「コンピュータプログラミング言語の歴史」ブラウン大学. 2023年3月2日閲覧。
- ^ Glück, Robert (2012). 「部分評価器からのコンパイラジェネレータのブートストラップ」。Clarke, Edmund、Virbitskaite, Irina、Voronkov, Andrei (編). Perspectives of Systems Informatics: 8th International Andrei Ershov Memorial Conference, PSI 2011, Novosibirsk, Russia, June 27 – July 1, 2011, Revised Selected Papers . Lecture Notes in Computer Science. Vol. 7162. Springer. pp. 125– 141. doi : 10.1007/978-3-642-29709-0_13 .
「Getting started」では、コンパイラ構築でお馴染みの「鶏が先か卵が先か」問題が提示されます。コンパイラをブートストラップするにはコンパイラが必要であり、コンパイラジェネレータのブートストラップも例外ではありません。
- ^ 「GCCのインストール:ビルド」 . GNUプロジェクト - フリーソフトウェア財団(FSF) .
外部リンク
ウィキメディア・コモンズにおけるコンパイルとリンクに関連するメディア