プログラミング言語のインタプリタの説明で「逐次機械語に翻訳する」という説明を見かけることがある。ググればそういう説明がたくさん出てくるので具体例は割愛する。
しかし、「機械語に翻訳する」という説明は好意的に言えば「誤解を招く言い方」で、率直に言うと「デタラメ」である。
そういう説明を書く人は、自分でインタプリタを書いたことがあるのだろうか?誰かが書いた間違った説明文をそのまま引き写しているのだろうか?
もちろん、世の中にはJITコンパイルする言語処理系もあるが、それはインタプリタのように使えたとしても「コンパイラ」なのではないか。
機械語に翻訳しなくてもプログラムは実行できる
「逐次機械語に翻訳する」という説明を書いた人は「プログラムを実行するのだから機械語を生成しているのだろう」と考えたのかもしれない。これは間違った推論だ。
重要な事実として、機械語に翻訳しなくてもプログラムは実行できる。
以下に、Brainfuckというプログラミング言語のインタプリタの実装例がある:
https://github.com/minoki/brainfuck-aarch64/blob/master/bfinter.c
これのどこに「機械語に翻訳」する処理があるだろうか?ない。どこにもないのだ。
理論的に言えば万能チューリングマシンがどうのこうのという説明ができるのかもしれないが、筆者はコンピューターサイエンスの全てに精通しているわけではないので、不用意なことは言わない。
機械語に翻訳するということはどういうことか
当たり前だが、「機械語に翻訳する」プログラムを書くには何かしらの形で機械語の知識が必要となる。ポピュラーなPCのCPUだとx86_64だし、最近のMacやスマホならAArch64の知識だ。あるいは、LLVMのようなフレームワークを使うとLLVM IRの知識さえあれば機械語を出力できるかもしれない(もちろん、LLVMを作る人には機械語の知識が必要だろう)。
私が書いた「機械語を出力する」系のプログラムを見てみよう。まずはBrainfuckコンパイラーを紹介する。
- https://github.com/minoki/brainfuck-aarch64/blob/master/bfcompile.c (AArch64)
- https://github.com/minoki/brainfuck-aarch64/blob/master/x86_64/bfcompile.c (x86_64)
まあ、これらは直接機械語を出力するわけではない。文字列操作でアセンブリ言語を出力するプログラムだ。それでも、 call
や bl
などのCPU依存の命令を駆使しているのがわかるだろう。こういうプログラムを書くにはアセンブリ言語の知識が必要だ。
本当に機械語を直接出力するプログラムも紹介しよう。これらはとあるVMのJITコンパイラーだ。
- https://github.com/minoki/icfpc2006/blob/master/aarch64/run_jit.c (AArch64)
- https://github.com/minoki/icfpc2006/blob/master/x86_64/run_jit.c (x86_64)
今度は文字列操作ではなく、バイト列や整数列の操作をやっていることが読み取れるのではないか。さらに、mmap
や __builtin___clear_cache
などの環境依存な関数を使っているのがわかるだろう。機械語を扱うのは環境依存な操作なのだ。
このように機械語を直接扱うには、当然機械語の知識を得る必要がある。x86_64ならIntelが出しているSDMという数千ページの文書(あるいはAMDのマニュアル)を読むし、AArch64ならArmのArchitecture Reference Manualという1万ページ越えの文書を読む必要がある。もちろん、全部読むのは現実的ではないので、必要な部分を拾い読みすることになる。
こういう、機械語についての話は、以前に記事を書いたので興味のある方はそちらを読んで欲しい:
では、インタプリタを書くにはこのように難解でCPUのアーキテクチャ依存な機械語の知識が必要なのか?というと、もちろんそんなことはない。先ほど載せたBrainfuckインタプリタは、AArch64やx86_64固有の知識は必要ないし、C言語が動く環境なら動くだろう(移植性がある)。
インタプリタに関する他の誤解
インタプリタについては「1行ずつ解釈する」みたいな言い方がされることもある。大抵のインタプリタについては、これも誤解と言って差し支えないだろう。普通はコードを全部読んで字句解析、構文解析などを先に済ませるからだ。プログラミング言語にもよるが、重要なのは構文木やVMの命令であって、行という単位ではない。
もちろん、「Windowsのバッチファイルを実行中に書き換えると書き換えた内容が反映される」という話もあるし、「1行ずつ解釈するインタプリタ」が存在することを否定するわけではない。
インタプリタについて真面目に勉強するには
インタプリタの作り方を知りたくなった人のために、「Crafting Interpreters」を紹介しておく。英語版はWebで無料で読める。日本語版も出版されている。
まあ私はWeb版をちょっと読んだくらいで、翻訳版は持っていない。あまりちゃんと読んでいない本をお勧めするのも良くないかもしれないが、自己責任ということで。
おしまい
言語処理系は面白いので沼に沈む人が一人でも増えてほしい。