Skip to content

Instantly share code, notes, and snippets.

@oguzalb
Created April 17, 2020 13:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oguzalb/f7874be636dca2bfcc3ec1264997256b to your computer and use it in GitHub Desktop.
Save oguzalb/f7874be636dca2bfcc3ec1264997256b to your computer and use it in GitHub Desktop.
A simple stack machine implementation for Python in Python
import dis
# Run this with python3 : )
class VM:
def __init__(self):
self.stack = []
def push(self, value):
self.stack.append(value)
def pop(self):
return self.stack.pop()
def call(self, function, args):
bytecode = dis.Bytecode(function)
constants = function.__code__.co_consts
local_vars = args + (
(function.__code__.co_nlocals - len(args)) * [None]
)
global_vars = globals()
var_names = function.__code__.co_names
for instruction in bytecode:
if instruction.opname == "LOAD_CONST":
self.push(constants[instruction.arg])
elif instruction.opname == "LOAD_FAST":
self.push(local_vars[instruction.arg])
elif instruction.opname == "STORE_FAST":
local_vars[instruction.arg] = self.pop()
elif instruction.opname == "LOAD_GLOBAL":
self.push(global_vars[var_names[instruction.arg]])
elif instruction.opname == "CALL_FUNCTION":
args = [self.pop() for arg in range(instruction.arg)]
func_to_call = self.pop()
self.call(func_to_call, args)
elif instruction.opname == "BINARY_ADD":
addition = self.pop() + self.pop()
self.push(addition)
elif instruction.opname == "RETURN_VALUE":
return
def func(a, b):
return a + b
glob = 10
def hede(a):
b = 4
total = (a + glob + b + 1)
return func(total, 2)
vm = VM()
vm.call(hede, [1])
result = vm.pop()
print(result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment