Skip to content

Instantly share code, notes, and snippets.

@inxanedev
Created July 11, 2020 16:01
Show Gist options
  • Save inxanedev/dc2f7e4dd38dee6a3f1462b98f34b3c4 to your computer and use it in GitHub Desktop.
Save inxanedev/dc2f7e4dd38dee6a3f1462b98f34b3c4 to your computer and use it in GitHub Desktop.
DIY Interpreter
import sys
def error(linenumber, clause):
print("Error at line \#" + str(linenumber) + ": " + clause)
sys.exit()
with open("code.diy") as f:
data = [line.lstrip("\t") for line in f.read().splitlines()]
labels = {}
for linenum, line in enumerate(data):
if line.endswith(":"):
labels[line.rstrip(":")] = linenum + 1
if "start" not in labels:
error(-1, "No start label specified")
linenum = labels["start"]
instr = [""]
class Stack:
def __init__(self):
self.stack = []
def push(self, value):
self.stack.append(value)
def pop(self):
return self.stack.pop()
def length(self):
return len(self.stack)
def last(self):
return self.stack[-1]
stack = Stack()
calls = []
while True:
inst = data[linenum].lower()
instr = inst.split(" ")
if instr[-1].endswith(":"):
error(linenum, "Section ended without exit instruction or jump to a label")
elif instr[0] == "push":
if instr[1] == "stack_len":
stack.push(stack.length())
else:
stack.push(int(instr[1]))
elif instr[0] == "goto":
if instr[1] in labels:
linenum = labels[instr[1]]
continue
else:
error(linenum, "No label of name " + instr[1] + " exists")
elif instr[0] == "goto-if-zero":
if instr[1] in labels:
if stack.last() == 0:
linenum = labels[instr[1]]
continue
else:
error(linenum, "No label of name " + instr[1] + " exists")
elif instr[0] == "pop":
stack.pop()
elif instr[0] == "print-ascii":
print(chr(stack.last()), end="")
elif instr[0] == "print-number":
print(stack.last(), end="")
elif instr[0] == "exit":
sys.exit()
elif instr[0] == "add":
stack.push(stack.pop() + int(instr[1]))
elif instr[0] == "call":
if instr[1] in labels:
calls.append(linenum + 1)
linenum = labels[instr[1]]
continue
else:
error(linenum, "No label of name " + instr[1] + " exists")
elif instr[0] == "back":
if len(calls) == 0:
error(linenum, "back instruction called but no calls have been made previously")
else:
linenum = calls.pop()
continue
else:
error(linenum, "Unrecognized instruction " + instr[0])
linenum += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment