ひとり勉強会

ひとり楽しく勉強会

スタックマシンとコンパイラ

YARV仮想マシンは、YARV Maniacs 【第 2 回】 で解説されているように、「スタックマシン」という計算モデルで作られています。スタックマシンというのは、一本のスタック(末尾へのpushとpopだけができる配列)を考えて、そこへデータを入れたり出したりする演算で計算を表現する考え方です。

たとえば、

> cat test.rb
(1+2) * (3+4)

こういうプログラムをYARVの命令列に直すと

> ~/yarv/rb/parse.rb test.rb
...
0000 putobject        1   # 1 をスタック に push      [1]
0002 putobject        2   # 2 をスタック に push      [1,2]
0004 opt_plus             # 二個pop&足した結果を push [3]
0005 putobject        3   # 3 をスタックに push       [3,3]
0007 putobject        4   # 4 をスタックに push       [3,3,4]
0009 opt_plus             # 二個pop&足した結果を push [3,7]
0010 opt_mult             # 二個pop&掛けた結果を push [21]
0011 leave

こうなります。この計算モデルの特徴は、コンパイラを作るのが簡単なことです。

FOO * BAR の計算結果をスタックにpushする命令列

を生成するには

FOO の計算結果をスタックにpushする命令列
BAR の計算結果をスタックにpushする命令列
スタックの値2つを取ってきてかけ算してpushする命令

と、式の各部分に対応する命令列を、周りのことはあまり気にせずそれぞれ作って、あとは機械的にガチャコンとconcatすれば完成です(基本的には)。というわけでYARVコンパイラも、おおむねこういう「式の各部分に対応する命令列をそれぞれ順番に作って(つまり再帰的にiseq_compile_eachを呼び出して)、ガンガンくっつけていく」という形でコンパイルしてます。