モテたい一心でbrainf*ckをPythonに実行させる

LLTigerで

#encoding:ruby

と書くだけで、Python上でRubyが動く、Ruby on Pythonが発表されました。

そして、よく分かりませんが、encodingのハックがゆくゆくはモテることにつながるらしいので、何か作ってみよう!

でも、Rubyはかなり大変そう。一番簡単なのは・・・・・・brainf*ckだ!

というわけで、

#bfcodec.py
from __future__ import unicode_literals

"""
This code is under PSF License.

Thanks Shibukawa Yoshiki!
http://shibu.jp/
"""
import encodings, codecs, sys, re
import bf

class aStreamReader(codecs.StreamReader):
    def readline(self, size=None, keepends=True):
        if getattr(self, "pysrc", None) is None:
            r = self.stream.read().decode("utf8")
            s = bf.compile_to_py(r)
            self.pysrc = s.splitlines(True)
        
        if self.pysrc:
            return self.pysrc.pop(0)
        else:
            return ''
        
def search_function(s):
    if s != "bf": 
        return None
    
    u8 = encodings.search_function("utf8")
    return codecs.CodecInfo(
        name='bf', 
        encode=u8.encode,
        decode=u8.decode,
        incrementalencoder=u8.incrementalencoder,
        incrementaldecoder=u8.incrementaldecoder,
        streamreader=aStreamReader, 
        streamwriter=u8.streamwriter
    )

def register():
    codecs.register(search_function)  # register our new codec search function

#bf.py
from __future__ import division, print_function, unicode_literals
__metaclass__ = type 

import io
from functools import partial
import sys

def compile_to_py(bfsrc):
    """
    >>> exec compile_to_py('''++++++++++[>++++++++++<-]>
    ... ++++.+++++++.--------.--.
    ... ''')
    hoge
    """
    fp = io.StringIO()
    p = partial(print, file=fp)
    
    p("import sys")
    p("ptr = 0")
    p("buf = {}")
    
    i = ""
    for c in bfsrc:
        if c == ">":
            p(i + "ptr += 1")
        elif c == "<":
            p(i + "ptr = max(0, ptr - 1)")
        elif c == "+":
            p(i + "buf[ptr] = buf.get(ptr, 0) + 1")
        elif c == "-":
            p(i + "buf[ptr] = buf.get(ptr, 0) - 1")
        elif c == ".":
            p(i + "sys.stdout.write(chr(buf[ptr]))")
        elif c == ",":
            p(i + "buf[ptr] = ord(sys.stdin.read(1))")
        elif c == "[":
            p(i + "while buf.get(ptr, 0):")
            i += " "
        elif c == "]":
            i = i[:-1]
    
    return fp.getvalue()
    
def main():
    import doctest
    doctest.testmod()

if "__main__" == __name__:
    main()
#sitecustomize.py
import bfcodec
bfcodec.register()

これらをsite-packagesにまとめて放り込むとヤれます。乙py

$>cat hello.bf
#encoding:bf
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
------------.<++++++++.--------.+++.------.--------.>+.
$>python hello.bf
Hello, world!