『RubyでつくるRuby ゼロから学びなおすプログラミング言語入門』を読んだ

タイトル通り、Rubyを使ってRubyインタプリタを作っていく面白いテーマの本。
プログラミング初心者も対象読者に入っているため、非常にコンパクトにまとまっており、140ページ程度でインタプリタを作れる。

RubyでつくるRuby ゼロから学びなおすプログラミング言語入門(紙書籍)www.lambdanote.com

Rubyの入門から始まっていくが、本当に最低限の機能しか扱わない。
クラスやオブジェクトという概念は全く出てこないし、メソッドもほとんど出てこない。
初心者のために内容を厳選したということだろうが、かなり思い切った構成になっている。

しかし、そんな「最低限の内容」だけでインタプリタ自作のような複雑で面白いことをやれるのが、興味深かった。

出てくる内容が、変数、条件分岐、配列、ユーザー定義関数、といったものばかりで、「本当に初心者向けだなー」と思いながら読んでいた。
そしてその「初心者向け」の機能だけでインタプリタを作っていくのは本当に面白かった。
言語機能について説明した後、それを使う機会(インタプリタ実装)がすぐに訪れるのも、入門書の構成として良いと思った。

Rubyの言語機能の説明もそこそこに木構造の説明に入っていく本書は、プログラミング入門書としてはかなり独特だと思う。
全編に渡り木構造再帰を使っており、以前読んだ『プログラミングの基礎』に似ているかもしれない。

薄くてカラフルなのも、入門書として素晴らしいと思う。全ページフルカラーになっている。

特に、抽象構文木をカラフルな図で表現してくれるのは素晴らしかった。
これのおかげで、扱っているデータの構造をビジュアルで理解できるし、実装すべき処理もすぐにイメージできる。

本書の担当編集者であり、出版元のラムダノート株式会社の創業者でもある鹿野さんが、プログラムによって木を描いていたらしい。 note.golden-lucky.net

こういった工夫のおかげで、プログラミング初心者でも学習を進めやすい内容になっていると思う。

とはいえ、本当の初心者よりも、インタプリタや抽象構文木、言語処理系といったものに興味のある人が本書のメインターゲットだと思う。
すごく簡単に、インタプリタや言語の実装という世界に触れることが出来る。

かなり初歩的な内容ではあるが、文字通り初歩、最初の第一歩にはなる。
パースとか抽象構文木とか、何となくで理解していた用語の概要をきちんと知ることが出来た。
「パースする」といったときに何が行われているかを、何となくイメージできるようになった。

実際の言語処理系はもっと複雑なものだろうけど、やっていることをイメージできる、概略を掴める、というのが最初の一歩として重要だと思う。

本書では構文解析は行わず、著者が作成し gem として提供されているライブラリを使う。
読者は、構文解析済みの抽象構文木を対象に、それを処理するためのプログラムを書いていく。
他にも要所要所でそのライブラリに作業を丸投げするが、それは決して本質を損ねるようなものではない。
むしろ「インタプリタづくり」という本質に集中できるよう、本書のテーマにおいては非本質的な諸々の作業を肩代わりしてくれていると言える。

以下、各章のメモ。

第1章

第2章

  • 変数、分岐、ループなどの基本的な概念について学ぶ

第3章

  • インタプリタを作るために、木というデータ構造を学ぶ。なぜなら、プログラムのような複雑なものを扱うのに適したデータ構造だから。
  • Rubyの「配列」で木を表現し、Rubyの「関数」で木を操作する

第4章

  • まずは四則演算のみをサポートしたインタプリタを作る
  • プログラムはただの文字列なので、まずはそれを木構造に変換する必要がある。この変換のこと構文解析、あるいはパースと呼び、それによって得られた木を構文木と呼ぶ。
  • 括弧や空白などの不要な情報を省いた構文木を抽象構文木という
  • プログラムを受け取る → 構文解析して抽象構文木にする → 関数で木を操作する というのが処理の流れ
  • 四則演算の場合、木の葉についてはその値を返し、木の節については2つの部分木の実行結果を演算子に従って計算する

第5章

  • 複数の計算式を並べたものを複文という
  • プログラムが計算式と大きく違うのは、複文になっていること
  • だからインタプリタも複文に対応させる必要がある
  • whileを使って複文に対応する
  • インタプリタに変数を覚えさせるのは、Rubyのハッシュによって実装する

第6章

  • 実装しようとしている言語をターゲット言語、インタプリタの実装に使っている言語をホスト言語という
  • インタプリタの本質は、ターゲット言語の言語機能をホスト言語の言語機能に丸投げして、そちらで処理すること
  • 本書の場合はMinRuby(ターゲット言語)の処理をRuby(ホスト言語)で実装している
  • 構文解析の段階で他の言語機能を使ったプログラムに置き換えて扱うものを、糖衣構文という

第7章

  • 関数の実装は、変数と同じようにハッシュを使ってインタプリタに覚えさせる
  • 「言語仕様」とインタプリタの「実装」は一致するとは限らない。プログラミング言語を学ぶときはそれを注意して、「実装」ではなく「言語仕様」を学ぶことが大切。

第8章

  • 関数の実装を拡張して、ユーザー定義関数をサポートする

第9章

  • 言語Xのインタプリタに必要な機能を言語Xだけで実装できれば、インタプリタを使ってそのインタプリタ自身を動かせるようになる。これをブートストラップという。
  • 前章まででMinRubyインタプリタに様々な機能を実装してきたので、あとは配列とハッシュを実装すればブートストラップが可能になる
  • データ構造をつくる記述を構築子という
  • MinRubyの配列の構築子とハッシュの構築子は、Rubyの言語機能をそのまま使う