PyPy で Grass を実装してみた - プログラマのネタ帳を読んで、
すごく楽しそうだったので、HQ9+を実装してみました。
こういう役に立ちそうで立たない実装を作るのは楽しかったです。
ソース
HQ9plus.py
import os, sys # So that you can still run this module under standard CPython, I add this # import guard that creates a dummy class instead. try: from pypy.rlib.jit import JitDriver except ImportError: class JitDriver(object): def __init__(self,**kw): pass def jit_merge_point(self,**kw): pass def can_enter_jit(self,**kw): pass jitdriver = JitDriver(greens=['program'], reds=[]) class HQ9Plus(object): def __init__(self, src): self._src = src self._count = 0 jitdriver.jit_merge_point(program=self._src) def run(self): _output = "" for str in self._src: if str == "H": _output += self._hello() elif str == "Q": _output +=self._print_source() elif str == "9": _output+=self._print_99_bottles_of_beer() elif str == "+": self._increment() else: _output+="some error occured" rtn = _output return rtn def _hello(self): return "Hello, world\n" def _print_source(self): return self._src + "\n" def _print_99_bottles_of_beer(self): _output = "" _list = range(1,100) _list.reverse() for i in _list: if i == 0: before = "no more bottles" after = "99 bottles" elif i == 1 : before = "1 bottle" after = "no more bottles" else: before = "%d bottles" % (i) after = "%d bottles" % (i - 1) if i == 0: action = "Go to the store and buy some more" else : action = "Take one down and pass it around" _output +="%s of beer on the wall. %s of beer.\n" % (before, before) _output +="%s, %s of beer on the wall.\n" % (action, after) _output +="\n" rtn = "" return rtn def _increment(self): self._count += 1 def parse(program): parsed = [] for char in program: if char in ('H', 'Q', '9', '+'): parsed.append(char) return "".join(parsed) def run(fp): program_contents = "" while True: read = os.read(fp, 4096) if len(read) == 0: break program_contents += read os.close(fp) program = parse(program_contents) print HQ9Plus(program).run() #program, bm = parse(program_contents) #mainloop(program, bm) def entry_point(argv): try: filename = argv[1] except IndexError: print "You must supply a filename" return 1 run(os.open(filename, os.O_RDONLY, 0777)) return 0 def target(*args): return entry_point, None def jitpolicy(driver): from pypy.jit.codewriter.policy import JitPolicy return JitPolicy() if __name__ == "__main__": entry_point(sys.argv)
test.hq9p
HHQ+HQ++HQ9+
実行の方法
translateの方法
- https://bitbucket.org/pypy/pypy/get/release-1.6.tar.bz2をダウンロードして展開する
- python pypy-pypy-release-1.6/pypy/translator/goal/translate.py --opt=jit hq9plus.py
- hq9plus-c というファイルが作成される
実行
- pure Pythonでの実行結果
$ time python hq9plus.py test.hq9p > /dev/null real 0m0.027s user 0m0.020s sys 0m0.000s
- translate.pyで作成されたファイルでの実行結果
$ time ./hq9plus-c test.hq9p > /dev/null real 0m0.004s user 0m0.000s sys 0m0.000s