Go言語でつくるインタプリタを読み終わった

Go言語でつくるインタプリタを読んで 実際に動くインタプリタを書いたので記事として残しておく。

感想

ここ1週間半程度、この本を読んでいた。 気分転換に楽しい本でも読もうと思って Go言語でつくるインタプリタを開いた。

写経しながら読んだが、良い本で、楽しく読める本だった。 また、この本はテスト駆動開発とは書いてないが テスト駆動開発のような形でテストを書いて失敗を確認した後 実装を書いてテストを確認するような流れで書かれている。

またテストが通ったタイミングなどで、「やったね!」とか「完璧だ!」とか「これだけなんだ!」とか 読者の気持ちを盛り上げてくれる言葉が書かれていて 読んでいくごとに実装していくごとに楽しくなっていった。

また、途中で紹介されていたPratt Parsersの記事も読んだ。 この記事はJavaでPratt Parserの説明をしてくれているが、とても分かりやすかった。 Javaなので、読みやすいし。

ちなみに、自分は、構文解析と簡単なインタプリタは書いたことはあるが、専門家ではないが 本で実装する言語に最低限必要なことは書かれているし、テストもあって試しやすい。 goで書いていたこともあって、テストの実行のサイクルが早かったのも良い体験だった。

字句解析や構文解析など、インタプリタを書いたことがない人にはオススメの本だ。 興味を持った人は読んでみてほしい。

ちなみに、マクロには興味がなかったので飛ばした。

拡張してみた部分

本には実装されていない機能として以下のような物を実装してみた。

  • runeを使ったlexer
  • tokenだけ小数点数のサポート(実際に実行しようとするとエラーで落ちる)
  • エスケープ文字(タブとか改行とか)
  • パイプラインオペレータ
  • 配列やハッシュ形式のDestructuring
    • let文におけるDestructuring
    • 関数リテラルにおける引数のDestructuring

実はruneや小数点数やエスケープ文字は昔書いたlexerを本の実装に合わせて移植したものである。 なので、今回実際に本に載ってないもので実装したのはパイプラインオペレータとDestructuringがメインになる。

パイプラインオペレータによって、以下のようなコードが動く。 (REPLで実行した例だ)

>> 2 + 2 | fn(x) { x }
4

また、Destructuringによって以下のようなコードも動く。 これは楽しい。

>> let [x] = [2]; x
2

>> let {x} = {"x": "2"}; x
2

>> 2 | fn(x) { x }
2

>> [1, 2] | fn([x, y]) { x + y }
3

>> {"x": 1, "y": 2} | fn({x, y}) { x + y }
3

パイプラインオペレータもDestructuringも比較的簡単に実装が出来たので楽しかった。 実際に実装したコードは以下のリポジトリに置いてある。

github.com

ちなみに、とりあえず動く形にしただけなので エラーハンドリングはだいぶ雑だ。

終わりに

Go言語でつくるインタプリタを読んで、本に書かれているのと同じくGo言語を使って、monkey言語を実装した。 パイプラインオペレータやDestructuringなども本には書かれていないが実装してみた。 基本的に読んでいて楽しいし、写経するだけでも楽しい本だった。

Go言語でつくるインタプリタは良い本だったので興味があったら読んでほしい。

終わり。