mini python演習ふりかえり

mini python演習も一段落したので、この数ヶ月のことを振り返ってみることにします。

ペアプロ的な意味で

べ、べつにこのエントリに反応したわけじゃないんだからねっ ペアプロ相手のすごいところ - 毛のはえたようなもの

人と一緒にプログラムを書く経験というのが今までなかったので、なかなか面白い経験となりました。一人で書いてると、思い付きでドラスティックな変更をポンポンとすることがよくあるのだけど、もう一人このコードをいじってる人がいると思うと、安易な変更を一歩踏みとどまって考える抑止力になるということがわかりました。shiroさんがどこかで書いていた「常に動くコードがある」ことを達成できるように(途中達成できてない時期もあったけど)気を遣いながらコードを書いてくということは、なかなか面白かったです。

ペアプロ相手としてのかえるさん(id:gomi-box女史)は、本人はどう思っているかしらないけれど、良い相手だったと思います。ハリボーもくれるし(^ω^)

今回は言語処理系のプログラムで、自分が大体どんなプログラムを書くか概要を把握できていて、かえるさんは(おそらく)把握できていない、という状態から始まりました。途中おいてけぼりにしてしまった感もあるけれど、俺がなんとなく手を引いただけで、全く未知のジャンルのプログラムを動くところまでもっていけたのは、かえるさんが誇れる結果です。

なんかバグがあるたびに(たまに俺が仕込んだバグだったりしても)音速で謝られることが多かったのだけど、バグを作ることは全然悪いことではない。むしろ俺が嫌いなのは、何も考えずに諦める態度、やろうともしない態度。未知のジャンルのプログラムを書くときには、バグの数だけやる気があって、何かを学んでいると言うことができます。バグは潰すだけだけど、やる気を作りだすのは大変。

デバッグ作業は、最初のときはコンパイラのエラーメッセージを「英語よみたくない」と言ってて(^ω^#)ピキピキ だったけど、口を酸っぱくして「エラー読め」と言っていたら、ちゃんとエラーを読んでくれるようになったので、ニコニコしています。

また、mini pythonの初期のコードの大部分を書いたのはかえるさんなので、そのベースがなかったら実はmini pythonができてなかったんじゃないか、という気もします。自分はいかんせん気分屋で、興味のない部分はどうも手が進まないのだけれど、そういう部分を書いておいてもらえたのは非常にたすかりました。高速化の段階でかなりの部分に手を入れたけど、手を入れるコードベースがあることでずいぶんと楽になったと思います。

ともあれ、おつかれさまでした。

技術的な意味で

言語処理系に興味をもったのが、去年の夏みずしまさんにPackrat Parsingについて教えてもらってからです。

最初は構文解析おもすれーと思って、図書館で借りた本で色々勉強しながら lingrのparsing roomでみずしまさんに馬鹿な質問ばかりをぶつけていました。突拍子もない質問に付き合っていただいたみずしまさんにはとても感謝しています。

その後、構文解析の勉強にと買ったModern compiler implementation in Cをちまちまと読みすすめていくうちに、「コンパイラ作りたい!」という思いがふつふつと湧いてきて、そこに来てちょうどいいタイミングで、mini python演習がはじまりました。最初からコンパイラは難しいだろうし、作る課題はインタプリタなので、最近なにかと話題のVMを自分の手で実装してみたい、と考えるようになったのですが、この時点では自分でVMを実装できる自信は皆無でした。

VMを実装するにはどうすればいいか、考えた結果やったことは次の3つです。

  • GaucheVM実装(vm.c)をひたすら読んで、disasmを繰り返す
  • 自分で簡単なプロトタイプを実装する
  • Modern compiler implementation in Cで、スタックフレームの章をひたすら読む

まず、Gaucheのコードが読めたことがとてつもなく有り難かった。VMとはどんなものか、想像もつかない段階で、vm.cを読んで「ただのswitchのループじゃん」とわかったこと、スタック操作はどうすればいいのかわかったこと、命令セットを決める指針を得られたこと、その他もろもろのエッセンスはGaucheからきています。今回のVMの80%はGaucheのエッセンスでできています、と言っていいくらいにGaucheは参考にさせていただきました。去年の11月あたりは、どこに行ってもvm.cを読んで、iPod touchで電車の中でもvm.cを読んで、なんとかVMの実装の手掛かりを得ようと必死でした。practical-scheme.net上にあるGaucheVM実装に関する資料も読み漁りました。Gauche作者のshiroさんには本当に感謝しています。

次にやったことが、自分で簡単なプロトタイプを書くこと。とにかく小規模でいいから、VMらしきものを作ってみれば感覚がわかるんじゃないか、と思い書いたのがTivi。これを書いた経験も、VM実装において有効でした。どうやって命令を決めて(今思うと、このプロトタイプの命令セットはイマイチだけど)、どうやって命令列を組み立てていくか、という骨子となりました。

2週間ほど前は、ひたすらスタックフレームの操作を理解するのに時間を費やしていました。Modern implementation in Cのスタックフレーム操作の章を何度読んでも、どうしてそんな操作をする必要がるのかが理解できず。しかし実装中のVMはスタックマシンなのでスタック操作は必須。とりあえず本にある方法は一旦忘れて、自分なりにやってみよう、と実装してみたものの、なかなか関数呼び出しやらループやらを実現できない。Gaucheのスタック操作のページとにらめっこして、また考えて、本を読んで、また考えて、としているうちに、徐々に「これでいけそうだ」という形が見えてきました。そして思い通りに動くように実装できた後に本を読んでみると、「このまんまじゃねぇか!」 考えて考えて、たどりついた先は自分が理解できなかったまさにその方法と同じ方法になっていて、おもしろいやら、俺ってばスゲー感やらで嬉しくなってしまったのがつい1週間ほど前の話です。一旦実装できてしまうと、今まで理解できなかった説明がするすると入ってくる。"実践"はやっぱり重要だな、と身にしみて感じました。

そんなこんなで、気がついたらVMの実装ができてしまいました。あらためてふりかえってみると、どう考えても自分ひとりではここまでこれなかったな、と思います。素晴しい書籍やWeb上の資料を書いてくれた方々、Gaucheのshiroさん、言語処理系の世界へのきっかけをくれたみずしまさん、ペアプロ相手のかえるさん、twitterやブログで助言や、コードに対する反応をくれた多くの人達、抱き枕のどーもくん、噛む力を鍛えてくれたハリボー、みんなのおかげです。ありがとうございました。

おまけ

graph.pyのベンチマーク結果がやたら悪かったのは、デバッグ用のprint文を追加して忘れていたのが原因でした。ということでベンチマークをとりなおしたもの。

来年はこれを超えるmini pythonがでてくるんでしょうか(^ω^)来年になったらτ先生に聞いてみよう。