Skip to content

Instantly share code, notes, and snippets.

@zelark
Created April 4, 2014 14:41
Show Gist options
  • Save zelark/9976074 to your computer and use it in GitHub Desktop.
Save zelark/9976074 to your computer and use it in GitHub Desktop.
python virtual machine
# http://tech.blog.aknin.name/2010/04/02/pythons-innards-introduction/
# http://tech.blog.aknin.name/category/my-projects/pythons-innards/
# http://akaptur.github.io/blog/2013/08/14/python-bytecode-fun-with-dis/
# from vm import VirtualMachine
# vm = VirtualMachine()
# vm.byte_LOAD_CONST('a')
# vm.byte_LOAD_CONST('b')
# vm.byte_BUILD_LIST(2)
# vm.byte_BUILD_LIST(0)
# vm.byte_ROT_TWO()
# vm.byte_STORE_NAME('x')
# vm.byte_STORE_NAME('y')
class VirtualMachine(object):
def __init__(self):
# The call stack of frames.
self.frames = []
# The current frame.
self.frame = None
# The data stack.
self.stack = []
self.return_value = None
self.last_exception = None
#my frame locals
self.f_locals = {}
def top(self):
"""Return the value at the top of the stack, with no changes."""
return self.stack[-1]
def pop(self, i=0):
"""Pop a value from the stack.
Default to the top of the stack, but `i` can be a count from the top
instead.
"""
return self.stack.pop(-1-i)
def push(self, *vals):
"""Push values onto the value stack."""
self.stack.extend(vals)
def popn(self, n):
"""Pop a number of values from the value stack.
A list of `n` values is returned, the deepest value first.
"""
if n:
ret = self.stack[-n:]
self.stack[-n:] = []
return ret
else:
return []
def peek(self, n):
"""Get a value `n` entries down in the stack, without changing the stack."""
return self.stack[-n]
## Stack manipulation
def byte_LOAD_NAME(self, name):
frame = self.frame
if name in frame.f_locals:
val = frame.f_locals[name]
elif name in frame.f_globals:
val = frame.f_globals[name]
elif name in frame.f_builtins:
val = frame.f_builtins[name]
else:
raise NameError("name '%s' is not defined" % name)
self.push(val)
def byte_STORE_NAME(self, name):
self.frame.f_locals[name] = self.pop()
def byte_LOAD_CONST(self, const):
self.push(const)
def byte_ROT_TWO(self):
a, b = self.popn(2)
self.push(b, a)
## Names
def byte_LOAD_NAME(self, name):
frame = self.frame
if name in frame.f_locals:
val = frame.f_locals[name]
elif name in frame.f_globals:
val = frame.f_globals[name]
elif name in frame.f_builtins:
val = frame.f_builtins[name]
else:
raise NameError("name '%s' is not defined" % name)
self.push(val)
def byte_STORE_NAME(self, name):
#self.frame.f_locals[name] = self.pop()
self.f_locals[name] = self.pop()
## Building
def byte_BUILD_LIST(self, count):
elts = self.popn(count)
self.push(elts)
@Victor-Lerman
Copy link

how to use it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment