誰かが新しいプログラミング言語を書くとき、彼らはそれを何でINに書きますか?


162

私の無知を許してください。私はPHPに手を出して、SOのブラウジングをウェットにしていて、何年もの間疑問に思ってきた質問をしなければならないのです。

まったく新しいプログラミング言語を書くとき、何を書いていますか?

これはおそらく私が途方もない敬意を払っているすべてのプログラマーにとって本当にばかげているように聞こえますが、それは私にとって戸惑う鶏と卵の問題です。職業はなんですか?自分自身に言う今日、私は新しい言語を発明するつもりです!そして、起動します...メモ帳?すべてのコンパイラは以前から存在していた言語に基づいて構築されていますか?気になる人は、これまでに考案されたすべてのプログラミング言語を1つの巨大な分岐ツリーにまとめることができます...ますか?

私のかすかな知性で、これは魅力的だと思います...教えてください!

回答:


193

それは愚かな質問ではありません。その素晴らしい質問です。

すでに答えたように、短い答えは「別の言語」です。

まあそれはいくつかの興味深い質問につながりますか?特定のハードウェア用に作成された最初の言語である場合はどうなりますか?組み込みデバイスで作業する人々にとって非常に現実的な問題です。すでに「別のコンピューターの言語」と答えました。実際、一部の組み込みデバイスはコンパイラーを取得できません。そのプログラムは常に別のコンピューターでコンパイルされます。

しかし、あなたはそれをさらに押し戻すことができます。これまでに書かれた最初のプログラムはどうですか?

まあ「高水準言語」用の最初のコンパイラは「アセンブリ言語」と呼ばれるもので書かれたでしょう。アセンブリ言語は、言語の各命令がCPUへの単一の命令に対応する言語です。非常に低レベルの言語であり、非常に冗長で、非常に手間がかかります。

しかし、アセンブリ言語を書く場合でも、アセンブリ言語を「機械語」に変換するには、アセンブラと呼ばれるプログラムが必要です。さらに戻ります。最初のアセンブラは「マシンコード」で書かれていました。コンピュータ自体の生の言語と直接1対1で対応する2進数で完全に構成されるプログラム。

しかし、それはまだ終わらない。未加工の数値のみが含まれているファイルでも、翻訳必要です。これらの生の数値をファイルに入れてコンピューターに取り込む必要があります。

初期のコンピュータの前面にスイッチの列があったかどうかはよくわかります。2進数を表すまでスイッチを切り替え、次に別のスイッチを切り替えて、その単一の番号をコンピューターのメモリに読み込みました。次に、ディスクファイルまたはパンチカードからプログラムを読み取ることができる最小限のコンピュータープログラムを読み込むまで、フリックを切り替え続けました。別のスイッチをフリックすると、プログラムが実行されます。80年代に大学に行ったとき、その能力を備えていながら、スイッチを備えたプログラムをロードする仕事を与えられなかったコンピューターを見ました。

そして、それよりも前に、コンピュータプログラムはプラグボードでハードワイヤードされなければなりませんでした!


20
+1、私はこの答えが質問の精神に本当に合うと思います。
stderr 2011

30
私はかつてアセンブラーIIクラスを受講しましたが、教授がなぜ選択科目を選んだのか尋ねました。「簡単なAが欲しかったから」という面白い答えを探しました。最良の答えはあると思いましたが、町にハニーウェル工場があり、次の人は「一日中マイクロコードを書いていて、高級言語を学びたい」と言っていました。
T.Rob

3
コード:コンピュータのハードウェアとソフトウェアの隠された言語」を強くお勧めします。真空管から高級言語用のコンパイラまで、基本的にこの回答と同じ内容をカバーしています。
MatrixFrog

コンピュータは、人間と同じように、比較的わずかな時間で進化しました。
Gaurav Ojha 2016年

さて、これはnonconstructiveコメントになりますが、それは...これはすべての図形、フォームや情報で華麗な華麗な答えです:-)書かれなければなら
ルカシュラデク

23

最も一般的な答えはCです。ほとんどの言語は、C、またはコールバックとFlexのような「レクサー」とYACCのようなパーサージェネレーターを組み合わせた Cのハイブリッドで実装されています。これらは、別の言語の構文を説明する目的で使用される言語です。場合によっては、コンパイルされた言語に関しては、最初にCで実装されます。次に、言語の最初のバージョンを使用して新しいバージョンが作成されます。(Haskellのように。)


1
一部の言語は、picolispなどのアセンブラーで記述されています。(blog.kowalczyk.info/article/picoLisp-Arc-before-Arc.html
教授ファルケン

1
プログラムlex / yacc(flex / bison)はどうですか?これらはC言語で言語を作成するための補足と見なされますか?
Dave、

1
最も一般的な答えがCであることを証明するものはありますか?
RichardOD 2009年

google.com/Top/Computers/Programming/Languages/Open_Sourceのリストを調べ始めたところ、 誤って言語10でエディターウィンドウを閉じてしまい、やりたいという動機を失いました。とにかく、これまでの約半分はCで実装され、残りのほとんどはCにブートストラップされました。
ファルケン教授、

3
Lex / Yacc(または代替)について言及する必要があると思います。一般的にC言語で言語を書き始めるのではなく、Cコードでサポートされるレクサーとパーサーを使用します。
スティーブロウ

14

多くの言語がブートストラップされています- それはそれ自体書かれています。なぜこれをしたいのかについては、自分のドッグフード食べることをお勧めします

私が参照するウィキペディアの記事では、鶏と卵の問題について説明しています。面白そうだと思います。


5
始めたばかりでは不可能です。
Michael Borgwardt、

1
はい、明らかに。しかし、多くの言語は、可能になればこのように書かれています。他の人にはないように指摘したかったのですが、それは重要なポイントだと思います。
RichardOD 2009年

ブートストラップという用語を使用する場合は+1。コンパイラを2回コンパイルする必要があるのは興味深いことです。1回目は明らかに、最低限必要なコンパイラーを使用し、2回目は、今作成したコンパイラーを使用します。コンパイラに最適化を追加したとしましょう。ビルドしたコンパイラーは、それらの最適化でコードを生成できますが、最適化コンパイラーで再度コンパイルするまで、それ自体は最適化されたコードを実行しません。

@ Les-はい、ブートストラップは興味深いコンセプトです。
RichardOD

2
ここにランダムなコメント。誰が最初に来たのか(鶏または卵)に関する昔からの質問に対する答えは、鶏が最初に来たということです。理由は、何かを複製/複製するには、複製/複製を行うために、最初に複製/複製を準備しておく必要があるということです。
SpicyWeenie 14

10

ほとんどすべての言語ですが、グラフやその他の複雑なデータ構造の操作に適した言語を使用すると、多くのことが簡単になります。プロダクションコンパイラは、パフォーマンス上の理由からCまたはC ++で記述されることがよくありますが、OCaml、SML、Prolog、Lispなどの言語は、言語のプロトタイピングには間違いなく優れています。

言語設計で使用される「小さな言語」もいくつかあります。Lexとyaccは、たとえば構文と文法を指定するために使用され、Cにコンパイルされます(ocamllex / ocamlyaccや他の多くの同様のツールなど、他の言語用のポートがあります)。

特別なケースとして、新しいLisp方言は、ほとんどの同じインフラストラクチャで便乗できるため、既存のLisp実装に基づいて構築されることがよくあります。Schemeインタープリターの作成は、Schemeのコードページの下で行うことができます。この時点で、新しい機能を簡単に追加できます。

基本的に、コンパイラーは単に何かを読み込んでそれを別の何かに変換するプログラムです-LaTeXソースをDVIに変換し、Cコードをアセンブリーに変換してから機械語に変換し、文法仕様をパーサーのCコードに変換するなど。ソース形式の構造(解析)、それらの構造の意味、データを単純化する方法(最適化)、および生成する出力の種類。インタープリターはソースを読み取り、直接実行します。(通訳は通常、書くのは簡単ですが、かなり遅くなります。)


4

実際、ほとんどどの言語でも好きなように書くことができます。RubyでCコンパイラを作成するのを妨げるものは何もありません。あなたがしなければならない「すべて」は、プログラムを解析して、対応するマシンコードを出力することです。ファイルを読み書きできる場合は、プログラミング言語で十分でしょう。

新しいプラットフォームでゼロから始める場合は、クロスコンパイルを実行できます。Javaまたはx86でネイティブに実行される新しいプラットフォーム用のコンパイラを記述します。PCで開発してから、プログラムを新しいターゲットプラットフォームに転送します。

最も基本的なコンパイラは、おそらくアセンブラとCです。


ただし、この「任意の」言語は再帰呼び出しをサポートする必要があります。それ以外の場合、構文アナライザーとパーサーを実装することは、本当の挑戦になるでしょう。

2
タスクに不適切な言語を選択した場合、それはあなた自身の責任です。これは、コンパイラー/インタープリターだけでなく、あらゆるプロジェクトで発生する可能性があります。
ziggystar 2009年

4

「新しいプログラミング言語の記述」は、技術的にはコードを必要としません。それはちょうどあなたの言語がどのように見えるか、そしてそれがどのように機能するかについての仕様を考え出しているところです。言語がどのようなものかを理解したら、実際に言語を「機能させる」ための翻訳者と通訳者を書くことができます。

翻訳者は、ある言語でプログラムを入力し、別の言語で同等のプログラムを出力します。インタプリタは、プログラムをある言語で入力して実行します。

たとえば、Cコンパイラは通常、Cソースコード(入力言語)をアセンブリ言語プログラム(出力言語)に変換します。次に、アセンブラはアセンブリ言語プログラムを受け取り、機械語を生成します。出力が得られたら、プログラムを実行するためにトランスレーターは必要ありません。これで機械語プログラムができたので、CPUはインタープリターとして機能します。

多くの言語は異なる方法で実装されています。たとえば、javacJavaソースコードをJVMバイトコードに変換するトランスレータです。JVMはJavaバイトコードを実行するインタープリター[1]です。実行javacしてバイトコードを取得した後は必要ありませんjavacもうません。ただし、プログラムを実行する場合は常にJVMが必要になります。

プログラムを実行するためにトランスレータを保持する必要がないという事実は、最終的に他の言語の「上位」層で実行することなく、言語を「ブートストラップ」することを可能にするものです。

[1]ほとんどのJVMは舞台裏で翻訳を行いますが、JVMへのインターフェースが「入力言語->出力言語」ではないため、実際にはトランスレーターではありません。


3

一般に、好きな言語を使用できます。たとえば、PHPはCで書かれています。どのコンパイラにもアクセスできない場合は、アセンブリ言語を記述し、それを手動でマシンコードにコンパイルする必要があります。


2
マシンコードをコンパイルする必要はありません。定義上、CPUの母国語です。
Stu Thompson、

1
そうだね。私が言うつもりだったのは、「アセンブリ言語などの機械コードを手動でコンパイルすること」でした。私は間違っているかもしれませんが、すぐにバイナリ/ 16進数としてコードを入力する人はほとんどいないと思います。
カイヴォスケルタジャ2009年

2

多くの言語は、最初に別の使用可能な言語で記述され、それ自体で再実装され、その方法でブートストラップされました(または、PHPやperlなどの外国語での実装を維持しました)。ただし、最初のアセンブラーのような一部の言語は、最初のCコンパイラは手動でアセンブリにコンパイルされました。

私はそれについて読んで以来、ブートストラップに興味を持っていました。詳細を知るために、自分でBFのスーパーセット(自分でEBFと呼んでいます)を作成して自分で試してみました。EBFの最初のバージョンには3つの追加のプリミティブがあり、最初のバイナリを手動でコンパイルしました。そうしていると、2ステップのリズムが見つかりました。1つのリリースで現在の言語で機能を実装し、実装された機能を利用するようにコードを書き直したスイートリリースがありました。この言語は、LISPインタープリターを作成するために使用できるほど表現力豊かでした

最初のリリースタグにソースと一緒に手動でコンパイルしたバージョンがありますいますが、コードは非常に小さいです。最後のバージョンはサイズとコードが12倍大きく、コードをよりコンパクトにすることができるため、現在のバージョンを手動でコンパイルすることは困難です。

エドモンド・グリムリー・エバンスは彼のHEX言語で同様のことをし ました

これを自分で行うことについての興味深い事柄の1つは、なぜあるものが現状のままであるのかを理解することです。私のコードは、小さな増分調整がゼロから設計されたのではなく、進化したように見える場合、製品でした。今日少しコードが外れているように見えるコードを読むときは、そのことを覚えておきます。


1

通常、システム開発に適した汎用プログラミング言語(C、Haskell、ML、Lispなど)を使用しますが、オプションのリストは長くなります。また、通常、言語実装用のドメイン固有の言語、つまりパーサーや字句解析ジェネレーター、LLVMなどの中間言語などが含まれます。おそらく、シェルスクリプト、テストフレームワーク、およびautoconfなどのビルド構成システムも含まれます。


1

ほとんどのコンパイラは、Cでない場合はCやACのようなプログラムを作成しましたが、Cではなくアセンブリ言語を使用します今何語で?Fortranの基本的なアルゴリズムlispのようなオブジェクト指向の構造化された言語仕様からのbnf文法のように見える「psedocodeと呼ばれるソースコードのフォーム」をマシンに書き込むことができます。


1
私は、疑似コードが機械可読であるとは思われません
Richard Tingle

0

さらに、バイナリまたはアセンブリ操作を関数に変換する必要があります。つまり、アセンブラー/コンパイラーのジョブであり、データと関数からオブジェクトに変換する必要があります。言語の実装、次に、「見る」の実装を認識するか、独自の関数、手順、およびデータ構造を定義する必要があります。これには、多くの知識が必要です。関数とは何かを自問する必要があります。心は言語シミュレーションになります。これにより、マスタープログラマーを他のプログラマーから分離できます。


0

私も数か月前にこの質問をしました。そして、私はいくつかの記事を読んだり、ビデオを視聴したりして、「soft」という自分の言語を書き始めるのに役立ちました。まだ完全ではありませんが、この旅から多くのことを学びました。

知っておくべき基本的なことは、コードスニペットを実行する必要がある場合のコンパイラの動作です。コンパイラーには、字句解析、セマンティックアナライザー、AST(抽象構文ツリー)などの多くのフェーズがあります。

私が新しい言語で行ったことはここにあります-http://www.singhajit.com/writing-a-new-programming-language/

あなたが初めて言語を書いているなら、すべてが最善であり、長い道のりがあります。


0

プログラミング言語とは何ですか?

プログラミング言語は、コンピューターと対話するためのちょうど1つの方法です。コンピュータはゼロと1しか理解できないため、最初は大まかに言えば(コンピュータは2つの状態しか取ることができないスイッチとしてトランジスタで構成されているため、これらの2つの状態を0と1と呼びます)、0,1での作業は困難でした。コンピューター科学者は、binary(0,1)のすべての命令から、アセンブリ言語と呼ばれるより人間が読める形式に1対1のマッピングを行うことを決定しました。

たとえば、次のような指示があった場合:

11001101

アセンブリでは、次のように呼び出されます。

LOAD_A 15

これは、レジスターaの内容をメモリー・ロケーション15にロードすることを意味します。前述のように、コンピューターのトランジスターまたはその他の2つの状態に対して0と1を選択するような規則にすぎません。このように、50命令のプログラムがあります。アセンブリ言語を覚える方が簡単でしょう。そのため、ユーザーはアセンブリコードを記述し、一部のプログラム(この場合はアセンブラー)は、コードを呼び出すときにコードをバイナリー命令または機械語に変換します。

しかし、コンピュータが毎日改良されるにつれて、より多くの命令を含むより複雑なプログラム、たとえば10000の余地がありました。

この場合、アセンブリのような1対1のマッピングは機能しないため、他の高水準プログラミング言語が作成されました。たとえば、ユーザーが作成した画面に何かを印刷するためのI / Oデバイスとの関係で約80の指示が必要な場合は、ここで何かを実行して、このすべてのコードを1つのライブラリにパッケージ化して、たとえばprintfのように呼び出すことができますまた、このprintfを関連するアセンブリコードに変換できる別のプログラムを作成し、そこからアセンブリが残りを実行します。彼らはそれをコンパイラと呼んでいます。

したがって、画面に何かを印刷したいすべてのユーザーは、すべての命令をバイナリまたはアセンブリで記述する必要がなくなり、printf( "something")と入力するだけで、コンパイラやアセンブラなどのすべてのプログラムが残りを実行します。今、他の長いコードは同じ方法でパッケージ化され、他の人の作業を容易にするために、数千行のコードをpythonで1つのコードに単純化して他の人が使用できるようにパックできることがわかります。

たとえば、Pythonで多くの異なるコードをパックし、モジュール(ライブラリ、パッケージ、または呼び出したいもの)を作成して、そのモジュールをmgh(ちょうど私の名前)と呼ぶとします。ここで、このmghを何らかの方法で作成したとします。

import mgh
mgh.connect(ip,port.data)...

ipとポート番号を指定してリモートサーバーに簡単に接続し、後でデータを送信できます(またはそのようなもの)。今では、1行ですべてを実行できますが、実際に行われるのは、mghファイルから取得された多くのコードが実行されていることです。パッケージ化は、実行プロセスを高速化するためではなく、他のプログラマの作業を容易にするためのものです。したがって、誰かが最初にコードを使用したい場合は、ファイルをインポートしてから、Pythonインタープリターがその中のすべてのコードを認識し、コードを解釈できるようにします。

プログラミング言語を作成して実行したい場合は、まず翻訳が必要です。たとえば、構文を理解してcに変換できるプログラムを作成するとします。 cに、残りはcコンパイラ、次にアセンブラ、リンカーなどによって処理されます。最初にcに変換する必要があるため、速度が遅くなるという代償を払う必要があります。

今あなたができるもう一つのことは、cで起こるのと同じように、すべてのコードを同等のアセンブリ言語に翻訳できるプログラムを作成することですが、この場合、プログラムはそれを直接行うことができ、そこから残りはリンカ。このプログラムはコンパイラと呼ばれています。

だから私が話していることは、システムが理解する唯一のコードは0,1なので、どういうわけか構文をそれに変換する必要があります。今、私たちのオペレーティングシステムでは、アセンブラー、リンカーなどの多くの異なるプログラム...コードをアセンブリに変換できれば、残りの部分を処理できるか、または私が言ったように、コードをその言語に変換することで他のプログラミング言語コンパイラを使用できることを伝えるために作成されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.