Skip to content

Instantly share code, notes, and snippets.

@pcostesi
Created October 5, 2011 04:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcostesi/1263655 to your computer and use it in GitHub Desktop.
Save pcostesi/1263655 to your computer and use it in GitHub Desktop.
S Interpreter
#!/usr/bin/env python
""" This is a simple and experimental version of an interpreter for the
S language. It doesn't aim to be complete, just correct.
"""
from collections import defaultdict
import re
TAG = r"\s*(\[\s*(?P<tag>[a-eA-E]\d+)\s*\])?\s*"
NXT = r"(?P<nxt>[a-eA-E]\d+)"
VAR = r"([XZ]\d+)|Y"
ADD = re.compile(TAG + "(?P<var>" + VAR + r")\s*<-\s*(" + VAR + r")\s*\+\s*1")
REM = re.compile(TAG + "(?P<var>" + VAR + r")\s*<-\s*(" + VAR + r")\s*-\*1")
JNZ = re.compile(TAG + r"IF\s+(?P<var>" + VAR + r")\s*!=\s*0\s*GOTO\s*" + NXT)
def extract(operations, line):
for operation in operations:
statement = re.match(operation, line)
if statement:
d = statement.groupdict()
return d.get('tag', None), operation, d['var'], d.get('nxt', None), line
class State(object):
def __init__(self, Y=0, **kwargs):
self.vars = defaultdict(lambda: 0)
self.vars["Y"] = Y
self.vars.update(kwargs)
self.ptr = 1 #instruction pointer
def add(self, var):
self.vars[var] += 1
def rem(self, var):
value = self.vars[var] - 1
if value < 0:
value = 0
self.vars[var] = value
def jnz(self, var):
return self.vars[var] == 0
def __str__(self):
pairs = ("\t- %s:\t%s" % (k, v) for k, v in sorted(self.vars.iteritems()))
return "State:\n" + '\n'.join(pairs)
class Interpreter(object):
def __init__(self, f):
self.f = f
self.operations = [ADD, REM, JNZ]
self.program = list(Interpreter.__parse(f, self.operations))
@staticmethod
def __parse(f, operations):
for line in f:
i = extract(operations, line)
if i is not None:
yield i
def __jump(self, nxt):
for i in xrange(len(self.program)):
if self.program[i][0] == nxt:
return i
return len(self.program) + 1
def execute(self, state=None):
if state is None:
state = State()
while True:
if state.ptr - 1 >= len(self.program):
break
tag, op, var, nxt, line = self.program[state.ptr - 1]
if op == ADD:
state.add(var)
if op == REM:
state.rem(var)
if op == JNZ:
if state.jnz(var):
state.ptr = self.__jump(nxt)
print state
continue
print state
state.ptr += 1
return state.vars["Y"]
if __name__ == "__main__":
import sys
with open(sys.argv[1]) as f:
i = Interpreter(f)
input_values = dict(("X%d" % (d + 1), int(v)) for d, v in enumerate(sys.argv[2:]))
print i.execute(State(**input_values))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment