Skip to content

Instantly share code, notes, and snippets.

@BenDavidAaron
Created February 5, 2022 03:32
Show Gist options
  • Save BenDavidAaron/dd70b212dbb9f692a4bc7e2d64c25183 to your computer and use it in GitHub Desktop.
Save BenDavidAaron/dd70b212dbb9f692a4bc7e2d64c25183 to your computer and use it in GitHub Desktop.
A barebones stack based virtual machine implemented in python
program_counter = 0
step_counter = 0
stack = []
def push(val):
global stack
stack.append(val)
return
def pop():
global stack
if not len(stack):
raise RuntimeError(f"You messed up on line {program_counter}")
return stack.pop(-1)
def add():
global stack
a, b = pop(), pop()
push(a + b)
def write():
global stack
print(pop())
def compare():
global stack
if pop() == pop():
push(1)
else:
push(0)
def jump(up):
global stack
global program_counter
if pop():
program_counter += up
program_counter = max(program_counter, 0)
instructions = {
"push": push,
"pop": pop,
"add": add,
"write": write,
"compare": compare,
"jump": jump,
}
def execute(program):
global program_counter, step_counter
program_counter = 0
step_counter = 0
program = program.strip()
lines = program.splitlines()
expressions = [tokenize(line) for line in lines]
while program_counter < len(expressions) and step_counter < 69:
op, args = expressions[program_counter]
print_state(op,args)
evaluate(op, args)
program_counter += 1
step_counter += 1
def tokenize(expression):
tokens = expression.split()
op = tokens[0]
args = [int(tk) for tk in tokens[1:]]
return op, args
def evaluate(op, args) -> None:
if args:
instructions[op](*args)
else:
instructions[op]()
def print_state(*args):
global step_counter
print(f"step: {step_counter}, stack: {stack}")
print(program_counter)
print(*args)
if __name__ == "__main__":
import sys
execute(sys.stdin.read())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment