Rustでlox言語のinterpreterを作っている話
TL, DR
Rustで
lox言語の
interpreterを実装している
なぜ
あまりにも暇を持て余していたのと、TypeScriptにContributeしたいが本体のコードがさっぱり読めなかった記憶から言語を実装して修行することにした。
実装言語はちょうど5周年だし、かれこれ2年ぐらい書きたいと思っていたRustをチョイスした。
とはいっても、実際何から始めればいいかさっぱりだったので、「プログラミング言語 自作」でググって、良さげだったこのサイトで最低限の処理の流れと用語を認識した。
このサイトは途中からyaccなど既存ツールを使って実装しており、1から車輪の再発明がしたい気分だったので別の資料を探すことにした。 他の日本語の資料も、ある程度、言語を実装することに詳しい人を対象にしており、1から丁寧に解説してくれているものを見つけられなかった。
そのため、じゃあ英語にするかーと思い、how to create programming language with rust
とかhow to implement...
とかでググって出てきた以下のredditを参考にした。
スレによるとこの辺がいいらしい。
- interpreterbook.com
- LLVM Tutorial: Table of Contents — LLVM 10 documentation
- The Programming Languages Zoo
- Table of Contents · Crafting Interpreters
Goでinterpreterとcompilerを作るやつは良さそうだったが、技術書典7の本が未だに積読になっている現状を鑑みると積読になる確率が高そうだったので見送り。
llvmのtutorialはちょっと読んで、llvm特有の話なのか言語実装の話なのかの切り分けがこんがらがりそうだったので見送り。
zooは、OCamlだったので心惹かれたが、説明がなさすぎて辛そうだったので見送り。
craftinginterpreters.comはちょっと読んだ限りでもかなり丁寧に解説してくれていて、実装言語もJavaでJavaScriptと一緒(暴論)なのでこいつをやることにした。
JavaとTypeScript、一緒に見える。見えない???
進捗どうですか?
初めて半月ぐらい経つが、ようやくprint文が動くようになった。
今までREPLに1 statementしか書いてこなかったのでちょっと文字列の扱える電卓だったが、print文が動くと一気にプログラミング言語感がでてきた。不思議。
この記事もprint文が動いたので記念に書いている。
ハマりポイント
JavaとRustの違い
JavaのinterfaceやextendsをどうやってRustでやればいいのかさっぱり分からず、2,3日ぐらいはRustのドキュメントの海を泳いでいた。ほとんど、ここにまとまっている。
Object Oriented Programming Features of Rust - The Rust Programming Language
他にもJavaのObject型の再現のためにTypeScriptのunion type的なものができないかと色々試したりしたが、できないっぽかったのでとにかくenumに固めていくことにした。
また、型の再帰をすると怒られが発生するので解決策を模索したりした。解決策はこちら。
Using Box<T> to Point to Data on the Heap - The Rust Programming Language
だいたい、公式のドキュメントやExampleをきちんと読み込めば分かるようになってるのすごい(こなみ)。
しばらく、Rustのstdモジュールのサイトと公式Bookを手放せそうにない。
lifetimeとownership
何もわからない。
scopeが簡単なうちは、エラーメッセージでトラブルシュートできていたが、parserを書いている最中に出ていた selfに対するsecond mutable borrow occurs here
がどうにもならず他のRust実装をチラ見した。再帰のせいでエラーになってるのかと推測して、そっち側で調査していたが、どうもlifetime annotationが食い違っていたのが原因だったっぽい。1日ぐらいは溶かした。&strをやめて、おとなしくStringを使うようにして、annotationを消したら動くようになった。Scannerをiteratorにしてる実装もあって、そっちの方がRustっぽそう。Rust、structのmethodに毎回self書かないといけないのでOOP向きではないのではと密かに思っている。ただ単に自分がOOPに馴染みが薄いだけかもしれない。
動かなかったコードはこれ。 https://github.com/sasurau4/lox-rust/commit/0b1369a8f4c343eb54b8aa1335830f26366c38fb
メモリの配置やらなんやらを気にしないでもいい感じにやってくれるJSに戻るといかに先人たちの叡智が偉大かを感じることができる。
楽しいところ
Pattern match
便利。多用している。Rust、欲しい文法がだいたい用意されているのでびっくりしている。
静的解析ツールが賢い
linterとcompilerが賢いので、彼ら?に従っておけば勝手に動くコードが出来上がる。エラーメッセージで「もしかして、これやりたい?ならこうじゃ」みたいなのが出てくるのはまじで助かる。JSと違ってpackageインストールしたりだとか設定がいらないのも大きい。
モチベ
自分で書いたプログラミング言語が動く。
動くと嬉しいので、毎回スクショしてissueに貼っている。
Progress · Issue #1 · sasurau4/lox-rust · GitHub
今の所、一節実装が終わるたびにプログラミング言語に近づいていくので毎回感動している。
小話
Crafting Interpreters にでてくるちょこちょこでてくる小話が面白い。今の所、負のマフィンがお気に入り。
これから
引き続き実装。次は静的型付け言語を実装したいが、入門用の文献があるのか分からない。Dragon bookは明らかに入門用ではなさそう。
言語を実装すると、プログラミング言語がいかに先人たちの叡智を結集したものかよく分かる & 文法を拡張することが難しいかが分かるのでおすすめ。