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)