プレゼンテーションZenに触発されてつくろうと思ったが途中で飽きた。あとは画像に埋め込むのと画像から抽出する部分を書けばいいんだけどね。まぁ気が向いたらまたやる。
やりたかったのはうさぎの写真にfib(5)を実行するコードを埋め込むとか。
re.Scannerの使い方を覚えたのでよしとしよう。
import sys import re from re import Scanner import Image LOGLEVEL = 2 def log(level, *msg): if level <= LOGLEVEL: print "\t".join(map(str, msg)) class VM(object): """ Virtual Machine """ def __init__(self,insns): self.insns = insns self.stack = [] self.heap = {} self.labels = self.find_labels(insns) def run(self): return_to = [] pc = 0 while pc < len(self.insns): if len(self.insns[pc]) == 1: insn = self.insns[pc][0] else: insn,arg = self.insns[pc] if insn == "push": self.push(arg) elif insn == "dup": self.push(self.stack[-1]) elif insn == "copy": self.push(self.stack[(arg+1)]) elif insn == "swap": x = self.pop() y = self.pop() self.push(x) self.push(y) elif insn == "discard": self.pop() elif insn == "slide": x = self.pop() for i in range(arg): self.pop() self.push(x) elif insn == "add": self.push(self.pop() + self.pop()) elif insn == "sub": y = self.pop() x = self.pop() self.push(x - y) elif insn == "mul": self.push(self.pop() * self.pop()) elif insn == "div": y = self.pop() x = self.pop() self.push(x / y) elif insn == "mod": y = self.pop(); x = self.pop() self.push(x % y) elif insn == "heap_write": value = self.pop() addr = self.pop() self.heap[addr] = value elif insn == "heap_read": addr = self.pop() value = self.heap[addr] self.push(value) elif insn == "jump": pc = self.jump_to(arg) elif insn == "jump_zero": if self.pop() == 0: pc = self.jump_to(arg) elif insn == "jump_negative": if self.pop() < 0: pc = self.jump_to(arg) elif insn == "call": return_to.append(pc) pc = self.jump_to(arg) elif insn == "return": if len(return_to) < 1: IndexError('return_to has no item') pc = return_to.pop() elif insn == "exit": return elif insn == "char_out": sys.stdout.write(chr(self.pop())) elif insn == "num_out": print self.pop() elif insn == "char_in": addr = self.pop() self.heap[addr] = ord(sys.stdin.read(1)) elif insn == "num_in": addr = self.pop() self.heap[addr] = int(sys.stdin.read()) pc += 1 print "プログラムの最後がexitではない" def push(self, item): if type(item).__name__ != 'int': raise TypeError('Not a Integer') self.stack.append(item) log(2, "stack op: ",self.stack) def pop(self): if len(self.stack) < 1: raise IndexError('stack has no item') return self.stack.pop() def jump_to(self, name): pc = self.labels[name] return pc def find_labels(self, insns): labels = {} for i,tp in enumerate(insns): if tp[0] == 'label': labels[tp[1]] = i return labels ### Scanner rnum = "([01]+)2" rlabel = rnum scanner = Scanner([ (r"00%s" % rnum, lambda s,token: ("push", to_num(re.sub(r'^00','',token)))), (r"020", lambda s,token: ("dup",)), (r"010%s" % rnum, lambda s,token: ("copy", to_num(re.sub(r'^010','',token)))), (r"021", lambda s,token: ("swap",)), (r"022", lambda s,token: ("discard",)), (r"012%s" % rnum, lambda s,token: ("slide", to_num(re.sub(r'^012','',token)))), (r"1000", lambda s,token: ("add",)), (r"1001", lambda s,token: ("sub",)), (r"1002", lambda s,token: ("mul",)), (r"1010", lambda s,token: ("div",)), (r"1011", lambda s,token: ("mod",)), (r"110", lambda s,token: ("heap_write",)), (r"111", lambda s,token: ("heap_read",)), (r"200%s" % rlabel, lambda s,token: ("label", to_label(re.sub(r'^200','',token)))), (r"201%s" % rlabel, lambda s,token: ("call", to_label(re.sub(r'^201','',token)))), (r"202%s" % rlabel, lambda s,token: ("jump", to_label(re.sub(r'^202','',token)))), (r"210%s" % rlabel, lambda s,token: ("jump_zero", to_label(re.sub(r'^210','',token)))), (r"211%s" % rlabel, lambda s,token: ("jump_negative", to_label(re.sub(r'^211','',token)))), (r"212", lambda s,token: ("return",)), (r"222", lambda s,token: ("exit",)), (r"1200", lambda s,token: ("char_out",)), (r"1201", lambda s,token: ("num_out",)), (r"1210", lambda s,token: ("char_in",)), (r"1211", lambda s,token: ("num_in",)) ]) def to_num(str): n = int(str[1:-1],2) if str[0] == '0': return n elif str[0] == '1': return -n else: raise TypeError('Not a Integer') def to_label(str): return str[:-1] ### Parser def parse_image(file): "pixelのrgpの合計のmod3をつなげた文字列を返す" modstr = "" im = Image.open(file) height,width = im.size for h in range(height): for w in range(width): r,g,b = im.getpixel((h,w)) modstr += str((r+g+b)%3) return modstr def extract_code(str): """10個以上の210の並びと10個以上の210の並びに挟まれた領域がコード領域""" return re.search(r'(210){10,}([012]+?)(210){10,}').group(2) if __name__ == '__main__': # print "Hello World\n=================" # t = [('push',10),('push',100),('push',108),('push',114),('push',111),('push',87),('push',32), # ('push',111),('push',108),('push',108),('push',101),('push',72),('char_out',),('char_out',), # ('char_out',),('char_out',),('char_out',),('char_out',),('char_out',),('char_out',), # ('char_out',),('char_out',),('char_out',),('char_out',),('exit',),] # vm = VM(t) # vm.run() print "token check\n================" tokens, remainder = scanner.scan("0001000012000110010020001101100200011100102000110111120001010111200010000020001101111200011011002000110110020001100101200010010002120012001200120012001200120012001200120012001200222") print tokens print "token -> vm\n================" vm2 = VM(tokens)