インタプリタの構成

ソースコードの区分

Ruby の README.EXT ではソースコードのファイルを四つに 分類して紹介している。まずはそれに従った分類を以下に示す。

  1. Ruby 言語のコア
  2. ユーティリティ
  3. Ruby コマンドの実装
  4. クラスライブラリ

「Ruby コマンドの実装」とはシェルから ruby ……と打って実行するときの ruby コマンドのことで、引数の解釈などを行っている部分だ。ruby コマンド 以外に Ruby インタプリタを利用したコマンドとしては Ruby を内蔵したもの、 たとえば jed や mod_ruby などが挙げられる。

また、クラスライブラリは拡張モジュールとほぼ同じ方法で実装されている。 ただしこのなかには Ruby のコアが依存しているクラスもあって、特に String と Array が全般に渡って重要である。

実行の概要

Ruby はインタプリタとして構築されている。つまり起動時にテキストの入力を 構文解析し、それに従って実行する。構文解析自体の詳しい説明は本筋でないので ここでは省略する。詳しくは Racc のユーザマニュアルや『Ruby を 256 倍使うための本・無道編 (ASCII)』を 参照のこと。しかし Ruby の動作を知るだけならばとりあえず以下のことを 知っていれば十分である。

まず入力は単なる「文字」の列である。次にスキャナと呼ばれる部分がこれを 「単語」に分割する。最後にパーサ (構文解析器) がその列の中に「構造」を見付ける。 「構造」とは、普段ソースコードを追う時のことを考えてみるとわかると思うが、 「if は条件式と本体で作られていて、その本体の中にはまた文の並びがあって…」 というような関係のことである。ソースコードがきれいに書かれているとすれば、 インデントで示してある階層関係がそのままインタプリタが見付ける構造の関係に なるはずである。ただしもちろんインデントで示せるのは文単位の構造だけであって、 文の中にも構造があることを忘れてはいけない。

さて、パーサが見付けた構造は構文木として出力される。構文木とは C の構造体を ポインタで木の形に連結したものである。その様子は例えば以下のようになる。


[if]
    [expr]            条件式
    [stmt]            条件が真の時に実行する文のリスト
    [stmt stmt]       条件が偽の時に実行する文のリスト
[while]
    [expr]            条件式
    [stmt stmt stmt]  条件が真の間実行される文のリスト
[assign]
    [lhs]             代入の左辺 (変数名など)
    [rhs]             代入の右辺 (代入する値)

[ ] で囲まれた部分が C の構造体でそれをノードと呼ぶ。インデントしたのは その上のノードからポインタでつながっているノードである。この例なら、 [if] ノードには三つのノードが保持されていて、それぞれが「条件」「真の文」 「偽の文」を意味しているということである。また同じ高さで並んでいるのは 逐次実行を表す。つまりここでは if while assign の順に実行される。

構文木で重要なのは、保持するノードの種類はなんでもいいという点である。 例えば上の例では「条件」に保持するノードは expr と書いてあるが、これは 単に「式」ということで、式であるノードならなんでもいい。例えば代入だとか 足し算、引き算、メソッドコール、定数、などなど、どれでもいいということである。 これで本当に大丈夫なのかはコアの説明のところで詳細を見ていくことにする。

構文木がコード (プログラム) の表現であるとすると、一方にはデータの 表現があるはずである。つまり Ruby オブジェクトの空間である。そして 言ってみれば Ruby インタプリタというのはこの二つの空間の接点を作り 出す機構である。このことは「コード」を「CPU」、「データ」を「メモリ」と 言い換えてみればさらにはっきりするであろう。

さて、この Ruby Hacking Guide ではまずこの二つの主役のうち、 データとの関りの側面から見ていくことにする。

Copyright (c) 1998-2002 Minero Aoki <aamine@loveruby.net>
This site is link free.