私の無知を許してください。私はPHPに手を出し、足を濡らしてブラウジングして、何年もの間疑問に思っていた質問をせざるを得ないように感じました。
まったく新しいプログラミング言語を書くとき、それを何と書くかin?
これはおそらく、私が非常に尊敬しているすべてのプログラマーにとって本当にばかげているように聞こえますが、それは私にとって厄介な鶏と卵のことです。職業はなんですか?自分に言ってください今日は新しい言語を発明するつもりです!その後、起動します...メモ帳?すべてのコンパイラは既存の言語に基づいて構築されているため、わざわざ1つの巨大な分岐ツリー上に考案されたすべてのプログラミング言語をグラフ化して、最終的には...に落ち着きました... 古い?
私の弱い知性で、私はこれが魅力的だと思います...私を教育してください!
それは愚かな質問ではありません。その素晴らしい質問です。
すでに答えたように、短い答えは「別の言語」です。
それは興味深い質問につながりますか?もしあなたの特定のハードウェアのために書かれた最初の言語なら?組み込みデバイスで働く人々にとって非常に現実的な問題。すでに答えたように、「別のコンピューター上の言語」。実際、一部の組み込みデバイスは決してコンパイラーを取得せず、それらのプログラムは常に別のコンピューターでコンパイルされます。
ただし、さらにプッシュバックできます。これまでに書かれた最初のプログラムはどうですか?
「高レベル言語」の最初のコンパイラは、「アセンブリ言語」と呼ばれるもので書かれていたでしょう。アセンブリ言語は、言語の各命令がCPUへの単一の命令に対応する言語です。非常に低レベルの言語であり、非常に冗長で非常に労力がかかります。
しかし、アセンブリ言語を作成する場合でも、アセンブリ言語を「マシン言語」に変換するには、アセンブラと呼ばれるプログラムが必要です。さらに戻ります。最初のアセンブラは「マシンコード」で記述されていました。コンピューター自体の生の言語と直接1対1で対応する2進数で完全に構成されるプログラム。
しかし、まだ終わらない。生の数字だけのファイルstillでも翻訳が必要です。ファイル内のこれらの生の数字をコンピューターに取り込む必要があります。
信じられないかもしれませんが、初期のコンピューターの前面にはスイッチの列がありました。 2進数を表すまでスイッチをひっくり返してから、別のスイッチをフリックすると、その1つの数字がコンピューターのメモリに読み込まれました。その後、ディスクファイルまたはパンチカードからプログラムを読み取ることができる最小限のコンピュータープログラムを読み込むまで、フリックを切り替え続けました。別のスイッチをフリックすると、プログラムの実行が開始されました。 80年代に大学に行ったとき、その容量はあるが、スイッチを備えたプログラムをロードする仕事が与えられなかったコンピューターを見ました。
それよりも早く、コンピュータープログラムは プラグボード でハードワイヤードする必要がありました!
最も一般的な答えはC
です。ほとんどの言語は、Cまたはコールバックと Flex のような「レクサー」と [〜#〜] yacc [〜#〜] のようなパーサージェネレーターを備えたCのハイブリッドで実装されます。 。これらは、1つの目的に使用される言語です-別の言語の構文を記述するために。コンパイルされた言語については、最初にCで実装される場合があります。次に、言語の最初のバージョンが新しいバージョンの作成に使用されます。 ( Haskell のように。)
多くの言語がブートストラップされています。つまり、 それ自体で記述されています です。これを行う理由については、 独自のドッグフードを食べる をお勧めします。
私が参照するウィキペディアの記事では、 鶏と卵 の問題について説明しています。かなりおもしろいと思います。
ほぼすべての言語ですが、グラフやその他の複雑なデータ構造の操作に適した言語を使用すると、多くのことが簡単になります。プロダクションコンパイラは、パフォーマンス上の理由からCまたはC++で記述されることがよくありますが、OCaml、SML、Prolog、LISPなどの言語は、おそらく言語のプロトタイピングに適しています。
言語設計で使用される「小さな言語」もいくつかあります。 Lexとyaccは、たとえば構文と文法の指定に使用され、Cにコンパイルされます(ocamllex/ocamlyaccなど、他の多くの同様のツールなど、他の言語用のポートがあります)。
特別な場合として、新しいLISP方言は、ほとんどの同じインフラストラクチャに便乗できるため、既存のLISP実装上に構築されることがよくあります。 Schemeインタープリターの記述は、コードページの下のSchemeで行うことができます。この時点で、新しい機能を簡単に追加できます。
基本的に、コンパイラとは、LaTeXソースをDVIに変換し、Cコードをアセンブリに変換してから機械語に変換する、文法仕様をパーサーのCコードに変換するなど、何かを読み込んでそれを別のものに変換するプログラムです。ソース形式の構造(解析)、それらの構造の意味、データを単純化する方法(最適化)、生成する出力の種類。通訳者はソースを読み、それを直接実行します。 (通訳は通常、記述が簡単ですが、はるかに遅いです。)
「新しいプログラミング言語の作成」には、技術的にはコードは一切含まれません。あなたの言語がどのように見え、どのように機能するかについての仕様を作成しているところです。自分の言語がどのようなものであるかがわかったら、翻訳者と通訳者を作成して、実際に言語を「機能させる」ことができます。
翻訳者は、ある言語でプログラムを入力し、別の言語で同等のプログラムを出力します。インタープリターは、ある言語のプログラムを入力して実行します。
たとえば、Cコンパイラは通常、Cソースコード(入力言語)をアセンブリ言語プログラム(出力言語)に翻訳します。次に、アセンブラはアセンブリ言語プログラムを取得して、機械語を生成します。出力が得られたら、プログラムを実行するのに翻訳者は必要ありません。これで機械語プログラムが作成されたため、CPUがインタープリターとして機能します。
多くの言語は異なって実装されています。たとえば、javac
は、JavaソースコードをJVMバイトコードに変換するトランスレーターです。JVMは、Javaバイトコード:javac
を実行してバイトコードを取得した後は、javac
は不要になりますが、プログラムを実行する場合は常にJVMが必要になります。
翻訳者がプログラムを実行するために保持する必要がないという事実は、他の言語のレイヤーやレイヤーの上で実行されることなく、あなたの言語を「ブートストラップ」することを可能にするものです。
[1]ほとんどのJVMは舞台裏で翻訳を行いますが、JVMへのインターフェースが「入力言語->出力言語」ではないという点で、実際には翻訳者ではありません。
実際、好きなほぼすべての言語で書くことができます。 RubyでCコンパイラを書くことを妨げるものは何もありません。あなたがしなければならないことは、プログラムを解析し、対応するマシンコードを出力することだけです。ファイルを読み書きできる場合は、おそらくプログラミング言語で十分です。
新しいプラットフォームでゼロから始める場合は、クロスコンパイルを行うことができます:Javaまたはx86でネイティブに実行される新しいプラットフォーム用のコンパイラを作成します。PCで開発し、その後、プログラムを新しいターゲットプラットフォームに転送します。
最も基本的なコンパイラは、おそらくアセンブラーとCです。
通常、好きな言語を使用できます。 PHPはCで記述されています。コンパイラにまったくアクセスできない場合は、アセンブリ言語を記述し、それを手動でマシンコードにコンパイルする必要があります。
多くの言語は最初に別の利用可能な言語で記述され、その後、それ自体で再実装され、その方法でブートストラップされました(またはPHPおよびPerl)のような外国語で実装を維持しました)が、最初のアセンブラは、最初のCコンパイラがアセンブリに手動でコンパイルされたように、マシンコードに手動でコンパイルされました。
私はそれについて読んで以来、ブートストラップに興味がありました。さらに学ぶために、自分でBFのスーパーセットを書いて自分でやってみました。これは [〜#〜] ebf [〜#〜] でした。 EBFの最初のバージョンには3つの追加プリミティブがあり、最初のバイナリを手でコンパイルしました。そうすると、2段階のリズムを見つけました。 1つのリリースで現在の言語の機能を実装し、実装された機能を利用するためにコードを書き直した甘いリリースがありました。この言語は、 LISPインタープリター を作成するのに使用できるほど表現力豊かでした。
最初のリリースタグ にソースと一緒に手でコンパイルされたバージョンがあり、コードは非常に小さいです。最後のバージョンは、サイズとコードが12倍大きく、コードをよりコンパクトにすることができるため、現在のバージョンを手作業でコンパイルするのは困難です。
エドモンド・グリムリー・エヴァンスは 彼のHEX言語
これを自分で行うことの興味深い点の1つは、いくつかのことがそのままである理由を理解することです。私のコードは、最初から設計されているのではなく、少しずつ調整されて進化したように見える製品です。今日コードを読むとき、それは少しおかしいと思うと思います。
ほとんどのコンパイラはCまたはCのようなプログラムであり、cではない場合、アセンブリ言語が最初の方法です。ただし、新しい言語を最初から記述する場合、プロトタイプ言語のマクロlibまたはソースコードがない場合は、独自の関数を定義する必要があります今、どの言語で? Fortranの基本的なアルゴリズムLISPのようなオブジェクト指向の構造化lang仕様からのbnf文法のように見える「psedocodeというソースコードのフォームをマシンに書くことができます。
通常、システム開発に適した汎用プログラミング言語を使用します。 C、Haskell、ML、LISPなど。ただし、オプションのリストは長い。また、通常、言語実装用のドメイン固有の言語、つまりパーサーと字句解析ジェネレーター、 [〜#〜] llvm [〜#〜] などの中間言語、およびおそらくいくつかのシェルスクリプトテストフレームワーク、ビルド構成システムなどautoconf。
さらにバイナリ、またはアセンブリ操作は、これらのオブジェクト機能がどのように表現されるべきかを見るためのソースファイルを持っていない場合、関数、アセンブラー/コンパイラーのジョブ、そしてデータと関数からオブジェクトに変換する必要があります言語の実装、それから、「見る」実装を認識するか、独自の関数、手順、およびデータ構造を定義する必要があります。これは多くの知識を必要とし、関数とは何かを自問する必要があります。これにより、マスタープログラマを他のプログラマから分離します。
私も数ヶ月前にこの質問をしました。そして、私はいくつかの記事を読んで、ソフトと呼ばれる自分の言語を書き始めるのを助けたいくつかのビデオを見ました。まだ完全ではありませんが、この旅から多くのことを学びました。
知っておくべき基本的なことは、コードスニペットを実行する必要がある場合のコンパイラの動作です。コンパイラには、字句解析、セマンティックアナライザ、AST(Abstract Syntax Tree)などの多くのフェーズがあります。
新しい言語で行ったことはここにあります- http://www.singhajit.com/writing-a-new-programming-language/
初めて言語を書く場合は、すべてのベストを尽くし、長い道のりがあります。