2009-08-22
*1250885641*セプキャン日記
共用マシンの接続テストでドタバタしていたのでid:Pasta-Kのマシンの接続チェックをするのを忘れていた。それ以外には目立った問題が発生しなかっただけにかなり悔しい。
さて、キャンプの雰囲気を伝えるためにちょっと書いてみるか。この課題、ささださんは当初gc.cに手を加えてgc時に音をならすというのを考えていたようだけども、開始直後にPasta-Kが一言「if文がtrueかfalseかで違う音をならしたい」と。うん、そっちのほうが面白そうだ、それでいこう。
じゃあ構文木からバイトコードに落とす過程でフックするようなバイトコードを挟もう、と簡単に方針を説明した後、じゃあcompile.cを読んで該当箇所を探してみよう!と言ってしばらく放置。書く前に十分読むことが重要。
しばらくしたら、ちゃんとifの条件式をコンパイルする部分にたどり着いていた。すばらしい。ところで当初はif(condition) thenをif(make_sound(condition)) thenに置き換えるつもりでいたのだけど、スタックマシンの挙動がまだあまりしっかりとイメージできていない状況で「引数の手前にレシーバが入る必要があるからスタックをローテートして」とか説明するのは難しいなぁと思った。thenの頭に音を鳴らす命令を入れようという提案があったのでそれで行くことにした。elseでも音が鳴らしたいと思ったら別の名前の関数を呼べばいいし。「thenのジャンプ先ラベルがずれると困るから末尾に入れよう」と思ったのだけどささださんにつっこまれて先頭に入れるのも難しくないことに気付く。
結果として
|ruby|
if condition
# then
else
# else
end
||
の形の構文木が
|ruby|
if condition
then_sound()
# then
else
else_sound()
# else
end
||
に相当するバイトコードにコンパイルされることになった。とりあえずpする命令を書いてみてきちんと呼ばれていることを確認。これがまたprelude.rbとかgem_prelude.rbなんていう勝手に読まれるコードがあってつまづくわけだが。まあ、なんとかなる。
次は音を鳴らす命令を書く。適当なライブラリを入れたりすればサウンドファイルを再生したりもできるはずなんだけど、とりあえずechoでOSSを叩いてみると音が鳴ったのでこれでいくことにした。きれいな音を出そうとして「間に合わなかったので音が出ません」になるよりは、ノコギリ波の音でも出ている方がいい。最初timesで1文字ずつ書いたせいで周波数を変えたつもりであんまり変わらないという罠にはまった。バッファされてある程度まとまってから書かれると思ったんだけどな。波形データを作ってから書き込む形に変更したらちゃんと期待通りの音が出るようになった。
などと試行錯誤しながら20時間という限られた時間でよくここまでできたと思う。間に合わなさそうだったら音を鳴らす部分とかは「作っておいたものがこちらにあります」って出そうかと思っていたけど、全部自力でやり遂げた。スライドに僕の名前は出ているけど、僕のコードは一行も入っていないんだよ。これは結構すごいと思うんだ。