import re ##################################################### # date:2012-11-13 # desc:Stack Class -- Utils ##################################################### class AyStack: def __init__(self, rsize = 100): self.data = [] self.rsize = rsize self.esp = -1 def size(self): return len(self.data) def push(self, i): if self.isFull(): raise 'AyStackOverFlow' else: self.data.append(i) self.esp = self.esp + 1 def pop(self): if self.isEmpty(): raise 'AyStackUnderFlow' else: r = self.data[-1] self.esp = self.esp - 1 del self.data[-1] return r def top(self): return self.data[-1] def isEmpty(self): if self.esp == -1: return True else: return False def isFull(self): if self.esp == self.rsize - 1: return True else: return False ##################################################### # date:2012-11-13 # desc:Method Stuff ##################################################### AyMethodTable = {} class AyMethod: def __init__(self): self.code = [] self.arg_num = 0 self.arg_name = [] self.arg_type = [] self.rtn_name = '' self.rtn_type = None self.methodname = '' self.max_locals = 0 def setMaxLocals(self, max_locals): self.max_locals = max_locals def setArgNum(self, arg_num): self.arg_num = arg_num def getArgNum(self): return self.arg_num def setArgName(self, arg_name): self.arg_name = arg_name def setArgType(self, arg_type): self.arg_type = arg_type def setRtnType(self, rtn_type): self.rtn_type = rtn_type def setRtnName(self, rtn_name): self.rtn_name = rtn_name def setMethodName(self, name): self.methodname = name def addCode(self, instruction): self.code.append(instruction) def loadFromFile(self, filename): for line in open(filename): for e in line.rstrip().split(' '): self.addCode(e) # corresponding with method's invocation class AyStackFrame: def __init__(self, method): self.locals = [] self.stack = AyStack() self.method = method self.eip = 0 if isinstance(self.method, AyMethod): for i in range(self.method.max_locals): self.locals.append(0) def setPrevStackFrame(self, StackFrame): self.prevStackFrame = StackFrame def readcode(self): if self.eip >= len(self.method.code): raise 'AyCodeOverFlow' else: rtn = self.method.code[self.eip] self.eip += 1 return rtn # dummy StackFrame for entry point dummyMethod = AyMethod() dummyStackFrame = AyStackFrame(dummyMethod) LastStackFrame = dummyStackFrame ##################################################### # date:2012-11-14 # desc:Exception ##################################################### class AyException(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return repr(self.msg) ##################################################### # date:2012-11-13 # desc:VM instruction set ##################################################### # ----------------------------------------- iload idx def Opcode_iload(StackFrame): validx = int(StackFrame.readcode()) val = int(StackFrame.locals[validx]) StackFrame.stack.push(val) # ----------------------------------------- istore idx def Opcode_istore(StackFrame): validx = int(StackFrame.readcode()) val = int(StackFrame.stack.pop()) StackFrame.locals[validx] = val # ----------------------------------------- ipush val def Opcode_ipush(StackFrame): const = int(StackFrame.readcode()) StackFrame.stack.push(const) # ----------------------------------------- iadd def Opcode_iadd(StackFrame): val1 = int(StackFrame.stack.pop()) val2 = int(StackFrame.stack.pop()) StackFrame.stack.push(val1 + val2) # ----------------------------------------- isub def Opcode_isub(StackFrame): val1 = int(StackFrame.stack.pop()) val2 = int(StackFrame.stack.pop()) StackFrame.stack.push(val1 - val2) # ----------------------------------------- imul def Opcode_imul(StackFrame): val1 = int(StackFrame.stack.pop()) val2 = int(StackFrame.stack.pop()) StackFrame.stack.push(val1 * val2) # ----------------------------------------- idiv def Opcode_idiv(StackFrame): val1 = int(StackFrame.stack.pop()) val2 = int(StackFrame.stack.pop()) StackFrame.stack.push(val1 / val2) # ----------------------------------------- if_cmpeq def Opcode_if_icmpeq(StackFrame): val1 = int(StackFrame.stack.pop()) val2 = int(StackFrame.stack.pop()) offset = int(StackFrame.readcode()) if val1 == val2: StackFrame.eip = offset # ----------------------------------------- if_cmpne def Opcode_if_icmpne(StackFrame): val1 = int(StackFrame.stack.pop()) val2 = int(StackFrame.stack.pop()) offset = int(StackFrame.readcode()) if val1 != val2: StackFrame.eip = offset # ----------------------------------------- if_cmplt def Opcode_if_icmplt(StackFrame): val2 = int(StackFrame.stack.pop()) val1 = int(StackFrame.stack.pop()) offset = int(StackFrame.readcode()) if val1 < val2: StackFrame.eip = offset # ----------------------------------------- iconst def Opcode_iconst(StackFrame): const = int(StackFrame.readcode()) StackFrame.stack.push(const) # ----------------------------------------- iinc def Opcode_iinc(StackFrame): idx = int(StackFrame.readcode()) const = int(StackFrame.readcode()) StackFrame.locals[idx] += const # ----------------------------------------- goto def Opcode_goto(StackFrame): offset = int(StackFrame.readcode()) StackFrame.eip = offset # ----------------------------------------- invoke def Opcode_invoke(StackFrame): global AyMethodTable methodName = str(StackFrame.readcode()) method = AyMethodTable.get(methodName) if method == None: print('!!! fail to invoke %s !!!' % methodName) prevStackFrame = StackFrame while prevStackFrame != dummyStackFrame: print('-----------------------------') print_local(prevStackFrame) print_stack(prevStackFrame) print('-----------------------------') prevStackFrame = prevStackFrame.prevStackFrame raise AyException('Function definition not found !') if isinstance(method, AyMethod): calleeStackFrame = AyStackFrame(method) calleeStackFrame.setPrevStackFrame(StackFrame) #print('>>> invoke %s' % method.methodname) arg_num = method.arg_num for i in range(arg_num - 1, -1, -1): calleeStackFrame.locals[i] = StackFrame.stack.data[arg_num - 1 - i] Interpreter(calleeStackFrame) if method.rtn_type: StackFrame.stack.push(calleeStackFrame.stack.pop()) # ----------------------------------------- ireturn # return from main loop in Interpreter # ----------------------------------------- print def Opcode_print(StackFrame): idx = int(StackFrame.readcode()) print(StackFrame.locals[idx]) OpcodeTable = { "iload" : Opcode_iload, "istore" : Opcode_istore, "ipush" : Opcode_ipush, "iadd" : Opcode_iadd, "isub" : Opcode_isub, "imul" : Opcode_imul, "idiv" : Opcode_idiv, "if_icmpeq" : Opcode_if_icmpeq, "if_icmpne" : Opcode_if_icmpne, "if_icmplt" : Opcode_if_icmplt, "iconst" : Opcode_iconst, "iinc" : Opcode_iinc, "goto" : Opcode_goto, "invoke" : Opcode_invoke, "print" : Opcode_print } ##################################################### # date:2012-11-13 # desc:Interpreter ##################################################### def Interpreter(StackFrame): if isinstance(StackFrame.method, AyMethod): code = StackFrame.method.code while StackFrame.eip < len(code): inst = code[StackFrame.eip] #print(inst) if (inst == 'ireturn'): return StackFrame.eip += 1 Opcode_func = OpcodeTable[inst] Opcode_func(StackFrame) ##################################################### # date:2012-11-13 # desc:Debug stuff ##################################################### def print_local(StackFrame): print('locals>>>>>>>>>>>>>>') for l in StackFrame.locals: print(str(l)) print('locals<<<<<<<<<<<<<<') def print_stack(StackFrame): print('stack>>>>>>>>>>>>>>') for s in StackFrame.stack.data: print(str(s)) print('stack<<<<<<<<<<<<<<') ##################################################### # date:2012-11-13 # desc:test ##################################################### if __name__ == '__main__': testMethod = AyMethod() testMethod.loadFromFile('bytecode.txt') testMethod.setMethodName('test_method') testMethod.setMaxLocals(1) calleeMethod = AyMethod() calleeMethod.loadFromFile('callee.txt') calleeMethod.setMethodName('callee_method') calleeMethod.setMaxLocals(1) AyMethodTable[calleeMethod.methodname] = calleeMethod testStackFrame = AyStackFrame(testMethod) testStackFrame.setPrevStackFrame(LastStackFrame) Interpreter(testStackFrame)
转载于:https://www.cnblogs.com/Anney/archive/2012/11/14/2770295.html