TRICK 2013 at RubyKaigi

tric/trick2013 · GitHub
「最悪のゴミ屋敷(Worst house of garbage)」賞をいただきました。まさか貰えるとは。ありがとうございます。
あと変態の称号もいただきました。私なんぞが変態だなんて真の変態に申し訳ないですが、ありがたく頂戴いたします。
コードはここ: trick2013/nari at master · tric/trick2013 · GitHub

簡単な解説

trick2013/remarks.markdown at master · tric/trick2013 · GitHubからの引用)
CRubyのオブジェクト空間自体を無限のテープとして利用したBrainf*ckの言語処理系です。

ObjectSpace.each_objectのブロックにメモリアドレスの低い順にオブジェクトが渡される特徴を利用しています。
この特徴を利用すれば、each_objectに特定のクラスに属するオブジェクトが渡ってきたときに、より高位のアドレスにさらに特定のクラスに属するオブジェクトを無理やり配置することで、each_objectのループが継続する状態を作り出すことができます。

上記の仕組みを利用して、Brainf*ckを作ってみました。
each_objectでテープのそれぞれのデータを1つずつ読み取り、それをBrainf*ckの1命令実行後のテープの状態に変換して高位のアドレスに対して配置します。
これを繰り返していくことによって、一度のeach_object呼び出しで完結したBrainf*ck言語処理系が実装可能となります。

また、1命令毎のテープ・ヘッドの状態をすべてオブジェクト空間自体に保存しているので、1命令毎の挙動を簡単に調べることができ、デバッグも容易です。

なぜ作ろうと思ったか

ObjectSpace.each_objectで無限ループできるのは知っていたのでこれを使って面白いことができないかあと考えた。
無限のデータ…無限のテープ…というとBrainf*ckじゃね?ということで作り始めた。
ObjectSpace.each_objectってテープのヘッドが右方向にしか進めない縛りがあるわけなんで、これでどうやってBrainf*ck作ろうかなぁ、と…。
それで結局は1命令ごとの状態をコピーしていくという作戦を取っている。
(他にも方法があれば教えてください…)

ObjectSpace.each_object(Cell)って感じで、クラスを指定してるのがちょっといけてない。
本当はCellクラスを作らずに、Bignumとか使ってやりたかったんだけど、それが難しかった(関係ないデータが意図せずできてしまうので)。
でももう少し頑張ればよかったかな。そこを指摘する浜地さんはさすが…。

あと、1行目でGC止めてますが、この止め方はイイ止め方だと思う。
僕が一番うまくGCを止められるんだ!

受賞コメント

  • 「受賞者のうち二人が中村ということで、中村一族はかなり変態ってことがわかったと思います」
  • 「ObjectSpace.each_objectの使い方に警鐘を鳴らしたかった」
  • 「メモリをかなり食います。Fibを動かすのに2GBくらい必要」
  • 「Brainf*ckなので日頃の業務などにお使いください」