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