importre######################################################date:2012-11-13#desc:Stack Class -- Utils#####################################################
classAyStack:def __init__(self, rsize = 100):
self.data=[]
self.rsize=rsize
self.esp= -1
defsize(self):returnlen(self.data)defpush(self, i):ifself.isFull():raise 'AyStackOverFlow'
else:
self.data.append(i)
self.esp= self.esp + 1
defpop(self):ifself.isEmpty():raise 'AyStackUnderFlow'
else:
r= self.data[-1]
self.esp= self.esp - 1
del self.data[-1]returnrdeftop(self):return self.data[-1]defisEmpty(self):if self.esp == -1:returnTrueelse:returnFalsedefisFull(self):if self.esp == self.rsize - 1:returnTrueelse:returnFalse######################################################date:2012-11-13#desc:Method Stuff#####################################################
AyMethodTable ={}classAyMethod: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=0defsetMaxLocals(self, max_locals):
self.max_locals=max_localsdefsetArgNum(self, arg_num):
self.arg_num=arg_numdefgetArgNum(self):returnself.arg_numdefsetArgName(self, arg_name):
self.arg_name=arg_namedefsetArgType(self, arg_type):
self.arg_type=arg_typedefsetRtnType(self, rtn_type):
self.rtn_type=rtn_typedefsetRtnName(self, rtn_name):
self.rtn_name=rtn_namedefsetMethodName(self, name):
self.methodname=namedefaddCode(self, instruction):
self.code.append(instruction)defloadFromFile(self, filename):for line inopen(filename):for e in line.rstrip().split(' '):
self.addCode(e)#corresponding with method's invocation
classAyStackFrame:def __init__(self, method):
self.locals=[]
self.stack=AyStack()
self.method=method
self.eip=0ifisinstance(self.method, AyMethod):for i inrange(self.method.max_locals):
self.locals.append(0)defsetPrevStackFrame(self, StackFrame):
self.prevStackFrame=StackFramedefreadcode(self):if self.eip >=len(self.method.code):raise 'AyCodeOverFlow'
else:
rtn=self.method.code[self.eip]
self.eip+= 1
returnrtn#dummy StackFrame for entry point
dummyMethod =AyMethod()
dummyStackFrame=AyStackFrame(dummyMethod)
LastStackFrame=dummyStackFrame######################################################date:2012-11-14#desc:Exception#####################################################
classAyException(Exception):def __init__(self, msg):
self.msg=msgdef __str__(self):returnrepr(self.msg)######################################################date:2012-11-13#desc:VM instruction set#####################################################
#----------------------------------------- iload idx
defOpcode_iload(StackFrame):
validx=int(StackFrame.readcode())
val=int(StackFrame.locals[validx])
StackFrame.stack.push(val)#----------------------------------------- istore idx
defOpcode_istore(StackFrame):
validx=int(StackFrame.readcode())
val=int(StackFrame.stack.pop())
StackFrame.locals[validx]=val#----------------------------------------- ipush val
defOpcode_ipush(StackFrame):
const=int(StackFrame.readcode())
StackFrame.stack.push(const)#----------------------------------------- iadd
defOpcode_iadd(StackFrame):
val1=int(StackFrame.stack.pop())
val2=int(StackFrame.stack.pop())
StackFrame.stack.push(val1+val2)#----------------------------------------- isub
defOpcode_isub(StackFrame):
val1=int(StackFrame.stack.pop())
val2=int(StackFrame.stack.pop())
StackFrame.stack.push(val1-val2)#----------------------------------------- imul
defOpcode_imul(StackFrame):
val1=int(StackFrame.stack.pop())
val2=int(StackFrame.stack.pop())
StackFrame.stack.push(val1*val2)#----------------------------------------- idiv
defOpcode_idiv(StackFrame):
val1=int(StackFrame.stack.pop())
val2=int(StackFrame.stack.pop())
StackFrame.stack.push(val1/val2)#----------------------------------------- if_cmpeq
defOpcode_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
defOpcode_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
defOpcode_if_icmplt(StackFrame):
val2=int(StackFrame.stack.pop())
val1=int(StackFrame.stack.pop())
offset=int(StackFrame.readcode())if val1
StackFrame.eip=offset#----------------------------------------- iconst
defOpcode_iconst(StackFrame):
const=int(StackFrame.readcode())
StackFrame.stack.push(const)#----------------------------------------- iinc
defOpcode_iinc(StackFrame):
idx=int(StackFrame.readcode())
const=int(StackFrame.readcode())
StackFrame.locals[idx]+=const#----------------------------------------- goto
defOpcode_goto(StackFrame):
offset=int(StackFrame.readcode())
StackFrame.eip=offset#----------------------------------------- invoke
defOpcode_invoke(StackFrame):globalAyMethodTable
methodName=str(StackFrame.readcode())
method=AyMethodTable.get(methodName)if method ==None:print('!!! fail to invoke %s !!!' %methodName)
prevStackFrame=StackFramewhile prevStackFrame !=dummyStackFrame:print('-----------------------------')
print_local(prevStackFrame)
print_stack(prevStackFrame)print('-----------------------------')
prevStackFrame=prevStackFrame.prevStackFrameraise AyException('Function definition not found !')ifisinstance(method, AyMethod):
calleeStackFrame=AyStackFrame(method)
calleeStackFrame.setPrevStackFrame(StackFrame)#print('>>> invoke %s' % method.methodname)
arg_num =method.arg_numfor i in range(arg_num - 1, -1, -1):
calleeStackFrame.locals[i]= StackFrame.stack.data[arg_num - 1 -i]
Interpreter(calleeStackFrame)ifmethod.rtn_type:
StackFrame.stack.push(calleeStackFrame.stack.pop())#----------------------------------------- ireturn#return from main loop in Interpreter
defOpcode_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#####################################################
defInterpreter(StackFrame):ifisinstance(StackFrame.method, AyMethod):
code=StackFrame.method.codewhile StackFrame.eip
inst=code[StackFrame.eip]#print(inst)
if (inst == 'ireturn'):returnStackFrame.eip+= 1Opcode_func=OpcodeTable[inst]
Opcode_func(StackFrame)######################################################date:2012-11-13#desc:Debug stuff#####################################################
defprint_local(StackFrame):print('locals>>>>>>>>>>>>>>')for l inStackFrame.locals:print(str(l))print('locals<<<<<<<<<<<<<>>>>>>>>>>>>>')for s inStackFrame.stack.data:print(str(s))print('stack<<<<<<<<<<<<<
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)