Rubyfuck ライブラリ

Rubyfuck というライブラリを作ってみました。以下の美しい Ruby のプログラムは Hello, world! を出力します。

Rubyfuck.new do |_|
  _.+_.+_.+_.+_.+_.+_.+_.+_.+_.+_[ _.>_.+_.+_.+_.+_.+_.+_.+_.>_.+_.+_.
 +_.+_.+_.+_.+_.+_.+_.+_.>_.+_.+_.+_.>_.+_.<_.<_.<_.<_.-_]._.>_.+_.+_.
 /_.>_.+_./_.+_.+_.+_.+_.+_.+_.+_./_./_.+_.+_.+_./_.>_.+_.+_./_.<_.<_.
 +_.+_.+_.+_.+_.+_.+_.+_.+_.+_.+_.+_.+_.+_.+_./_.>_./_.+_.+_.+_./_.-_.
 -_.-_.-_.-_.-_./_.-_.-_.-_.-_.-_.-_.-_.-_./_.>_.+_./_.>_./_
end

Rubyfuck は brainfuck と以下の規則で相互に変換できます。

brainfuck Rubyfuck
> _.>
< _.<
+ _.+
- _.-
, _.*
. _./
[ _[
] _].

brainfuck から Rubyfuck に変換するメソッドもあります。

puts Rubyfuck.from_brainfuck(<<END)
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+
++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
END

Rubyfuck のソースコードです。ぜひご利用下さい。

class Rubyfuck < String
  def initialize(*x); block_given? ? eval(yield(self)) : super; end
  def +(*x); f("a[i] += 1;", x); end
  def -(*x); f("a[i] -= 1;", x); end
  def >(*x); f("i += 1;", x); end
  def <(*x); f("i -= 1;", x); end
  def /(*x); f("putc a[i]; ", x); end
  def *(*x); f("c = $stdin.getc; a[i] = c if c;", x); end
  def [](*x); f("while (a[i] ||= 0) != 0;", x, "end;"); end
  def _; self; end
  def f(s, x, t = ""); Rubyfuck.new(m + s + x.join + t); end
  def m; "a ||= []; i ||= 0; a[i] ||= 0;" + self; end

  def self.from_brainfuck(s)
    h = { ">" => ".>", "<" => ".<", "+" => ".+", "-" => ".-",
          "," => ".*", "." => "./", "[" => "[ ", "]" => "]." }
    "Rubyfuck.new {|_| " + s.gsub(/./m) {|x| "_#{h[x]}" if h[x] } + "_ }"
  end
end

余談。以下のように使うとおしゃれです。

#!/usr/bin/env ruby -W0

require "rubyfuck"
ck = Rubyfuck
def (Rubyf = Object.new).*(x); x; end

Rubyf*ck.new do |_|
# ...
end