「プログラミング言語の構築方法:成功への(困難な)道のり」
Building Programming Languages The (Challenging) Path to Success
正直に言って、難しいと言っても過言ではありません。
私の前の記事では、プログラミング言語の構文と、それを構築する方法の一般的なアイデアについて説明しました。
しかし、最終的な成果に向かう旅について別の記事を書くことにしました。なぜなら、正直に言うと、旅は上昇よりも下降のほうがずっと多く、乗り越えなければならない課題は本当に圧倒的でした。この記事が、同じようなプロジェクトに取り組んで同じような困難に直面している人々に対して、諦めずに進んでいくことを励まし、自分自身も同じ立場にいた他の誰かが目標を達成したことを知ってもらう助けになればと思います。
しかし、なぜ気にすべきなのでしょうか?
あなたたちは皆、データサイエンスであるか、古き良きPythonやJavaから来た背景を持っています。
たとえ自分自身のプログラミング言語を構築することに興味がなくても、この経験を通じて向上したソフトスキルの多くは、特にプログラミングに興味がある方々にとって、共感できる(そしておそらく励みになる)ものでしょう。
- モジラのコモンボイスでの音声言語認識 — Part I.
- エッジエモーション認識:リアルタイム音声分析による人間と機械の相互作用の向上
- 「機械学習、ブロックチェーン技術はフェイクニュースの拡散に対抗するのに役立つかもしれません」
プログラムを書くときに、すべての行が正しく見えるのに、解読がほぼ不可能な謎めいたエラーが表示され、やる気を失い、諦めようと考えることが何度もあります。
私は言語を構築する際に、これらのよくある問題に何度も直面しました。そして、最終的にそれらを乗り越え、持ちこたえた方法が、この記事を進めるうえで記憶に残るメッセージを伝えることを願っています。
はじめに
このアイデアは、私が8年生(または9年生、正確には覚えていません)のときに最初に思い浮かびましたが、当時は条件分岐や繰り返しループさえほとんど理解していませんでしたので、忘れてしまいました。
しかし数年後、同じアイデアが私の頭に再び思い浮かびましたが、今度はどうやって始めればいいのかさっぱりわかりませんでした。
それで、他の何かわからないことと同様に、私はGoogleで検索しました。
「自分自身のプログラミング言語を作る方法」。
そして、結果はかなり有望でした。私はそれぞれの結果を一つ一つ詳細に調べるのに長い時間を費やし、その要点を押さえました:
言語には2つのタイプがあります。インタプリタ型とコンパイル型です。インタプリタ型の言語は構築が比較的簡単ですが、実行速度は遅くなります。一方、コンパイル型の言語はコードを機械語に変換してから実行します(コンパイル型の言語は一般的に速いです)。
言語を構築する一般的なプロセスは以下の通りです:
- 言語の目的と構文を定義する: これは私にとって非常に簡単でした(数学に関連する言語を構築したいと思っていました)。そして、自分自身にいくらかの作業を省略し、また言語をできるだけ高レベルにするために、いくつかの(必須で有用な)関数と、関数と浮動小数点数の2つの変数しか保持しないことにしました。
- 字句解析器とパーサーを構築する: 字句解析器は任意の言語の最初のコンポーネントであり、コードの各単語/フレーズを異なるカテゴリ(キーワード、演算子、コメントなど)に配置します。しかし、これらのレキシム単体では意味を持ちません。それらを理解するためには、パーサーを構築する必要があります。パーサーは、レキシムが言語の構文に従っていることを確認し、それらを抽象構文木(AST)に配置します。
- コードの実行: ASTの各ノードは、元の字句解析器によって収集されたトークンの1つを表し、関数名も含まれます。したがって、ASTを実行することで、書かれたコードを行ごとに実行することができます。これがインタプリタ型プログラミング言語の一般的な基礎です。
しかし、コンパイラにはいくつかの追加手順が必要です。LLVMやlibgccjitなどの人気のあるライブラリを使用して、コードをコンパイルされた実行可能ファイルに変換する必要があります。
コンパイルされたものか、インタプリターか?
一方で、自分でインタプリター言語を作ることもできますが、これは非常に難しく、多くの時間と努力を必要とします。一方で、自分でコンパイルされた言語を作ることもできますが、これはさらに難しく、より多くの時間と努力を必要とします。
しかし、自分でコンパイルされた言語を作るというアイデアは非常に魅力的に思えましたので、ついその罠にはまってしまいました。
アドバイス:やらないでください。
LLVMを使用してコンパイラを作るためのリソースは利用可能です(LLVMに関する100秒のビデオは、楽しいだけでなく、ある程度教育的でもありますので、ぜひおすすめです)。しかし、その複雑さのために、ドキュメンテーションを読むだけで迷ってしまいました。
おそらく、Javaの基礎を学ぶ方が、LLVMを使用してコンパイラを作る基礎を学ぶよりも早く学べると思います。
時間の無駄(それでいいのか)?
残念ながら、私は最初にLLVM、そしてlibgccjitを使いこなすために2か月以上も時間を費やしました。後者はより有望であり、私はコンパイラのためのコードさえ書きましたが、その後、libgccjitパッケージの設定に関連する多くの問題に直面しました。GitHubからそのソースコードをダウンロードして、私のコンパイラコードと同じディレクトリに配置するほどまでに至りましたが、それでも何もうまくいきませんでした。RedditやStackOverflowのスレッドを何時間もスクロールしましたが、どうにもなりませんでした。
StackOverflowですら助けてくれないとき、何かが非常におかしいです。
諦めかけて
この時点で、私は本当に新たな低みに落ちていました。長い間何の進歩もなかったため、自分でlexerとparserをゼロから作成するという作業など、自分の行ったすべての作業を価値を下げてしまいました。popularなlex/yaccやflex/Bisonのツールを使わずにです。この時点で私は自問しました。「(仮想の)ゴミ箱にすべてを捨てるべきでしょうか?」。はいと言いたくなる気持ちもありましたが、特にコーディングに関連するプロジェクトの場合、簡単には諦めません。
そこで、私は散歩に行って頭を冷やし、再びゼロから始めることにしました。今度は、インタプリター言語の構築を目指して。
ついに完成。
自分でインタプリターを作ることに決めた後、Cを捨ててPythonに戻るという難しい決断もしました。通常の状況では、インタプリターの遅さを補うために、低レベルの言語を使用することが最適です。
しかし、私は絶望的な時期にいたのです。そんな時には、必死の努力が必要です。
インドに戻った後、私は次の1週間、眠らずに24時間働きました(朝食、昼食、夕食を除くと21時間程度です。私はゆっくり食べる方です)。
そして、次に起こったことは、私にとって初めて起こったことであり、二度と起こることはないでしょう。私のコードは最初の試みで動作しました!デバッグもなく、もう混乱もありません。
ソースコードを実行したとき、レクサーやパーサー、ASTなど、すべてのコンポーネントが正しく動作し、コードの各行を正しく実行しました。
振り返りと最後のメモ
上記の引用はありきたりかもしれませんが、それはその妥当性に損ないを与えるものではありません。AdvAnalysisを構築する過程で、成功よりも失敗の方がはるかに多くありましたが、最終的には成功しました。
自分でプログラミング言語を構築する際に注意すべき点(コンパイルされたものとインタプリターの違い、どのプロセスを追うかなど)を学ぶことができますが、私が学んだ(そしてあなたも学んでくれたことを願っている)主な教訓は、どれだけ解読しづらいエラーに出くわしても、最終的には期待通りに動作するということです。ただし、忍耐力を持ち、ゼロから始めて異なるアプローチを取る能力がある場合に限ります。
正直に言うと、プログラミング愛好家の皆さんなら、おそらくすでにそれを知っていることでしょう。:)
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles