Skip to content

Instantly share code, notes, and snippets.

@m-ender
Created April 10, 2015 10:58
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 m-ender/5f5688758c7171a6675c to your computer and use it in GitHub Desktop.
Save m-ender/5f5688758c7171a6675c to your computer and use it in GitHub Desktop.
Modified Prelude interpreter. (http://esolangs.org/wiki/Prelude)
#!/usr/bin/python
import sys
NUMERIC_INPUT = True
NUMERIC_OUTPUT = True
try:
filename = sys.argv[1]
except:
print "Usage:", sys.argv[0], "<filename>"
raise SystemExit
try:
inFile = file(filename)
except:
print "Error when opening", filename
raise SystemExit
# code is kept as a list of voices, each voice a string
code = []
firstLine = True
eof = False
while not eof:
# read batch of lines
batch = []
while 1:
line = inFile.readline()
if line == '': eof = True
if line == '' or line.rstrip() == '*':
break
batch.append(line.rstrip())
maxLen = max([len(b) for b in batch])
batch = [b + ' '*(maxLen - len(b)) for b in batch]
if firstLine:
code = batch
firstLine = False
else:
if len(batch) != len(code):
print "Error in the program: number of voices changes"
raise SystemExit
for i in range(len(batch)):
code[i] += batch[i]
class Stack:
def __init__(self):
self.data = []
def push(self, value):
if self.data or value != 0: self.data.append(value)
def drop(self):
if self.data: self.data.pop()
def top(self):
if self.data: return self.data[-1]
return 0
def pop(self):
value = self.top()
self.drop()
return value
numVoices = len(code)
numInstructions = len(code[0])
stacks = [Stack() for x in range(numVoices)]
topValues = [0 for x in range(numVoices)]
# establish loop couplings
loopStack = []
loops = {}
for cp in range(numInstructions):
curr = [voice[cp] for voice in code]
if curr.count('(') + curr.count(')') > 1:
print "Error in the program: More than one bracket; position", cp
raise SystemExit
if '(' in curr:
loopStack.append((cp, curr.index('(')))
if ')' in curr:
if not loopStack:
print "Error in the program: extraneous closing bracket; position", cp
raise SystemExit
openingPosition, openingVoice = loopStack.pop()
loops[openingPosition] = cp
loops[cp] = openingPosition, openingVoice
if loopStack:
print "Error in the program: not enough closing brackets"
raise SystemExit
# now, actually execute the program
cp = 0 # code pointer
while cp < numInstructions:
# technically we're supposed to shuffle our voices to make sure to perform IO
# in random order, but screw that for now
next_cp = cp+1 # can be modified by ( )
for voice in range(numVoices):
i = code[voice][cp] # current instruction
if i == '^':
stacks[voice].push(topValues[(voice-1) % numVoices])
elif i == 'v' or i == 'V':
stacks[voice].push(topValues[(voice+1) % numVoices])
elif i == '+':
stacks[voice].push(stacks[voice].pop() + stacks[voice].pop())
elif i == '-':
b = stacks[voice].pop()
a = stacks[voice].pop()
stacks[voice].push(a-b)
elif i == '#':
stacks[voice].drop()
elif i == '?':
if NUMERIC_INPUT:
try:
stacks[voice].push(int(raw_input() or 0))
except Exception, e:
stacks[voice].push(0)
else:
char = sys.stdin.read(1)
if not char: char = '\0'
stacks[voice].push(ord(char))
elif i == '!':
if NUMERIC_OUTPUT:
print stacks[voice].pop()
else:
sys.stdout.write(chr(stacks[voice].pop()))
elif i == '(':
if stacks[voice].top() == 0:
next_cp = loops[cp] + 1
elif i == ')':
openingPosition, openingVoice = loops[cp]
if topValues[openingVoice] != 0:
next_cp = openingPosition + 1
elif i in '0123456789':
stacks[voice].push(int(i))
topValues = [stacks[i].top() for i in range(numVoices)]
cp = next_cp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment