Vague/Quintopia
Jump to navigation
Jump to search
An implementation of Vague by User:Quintopia. This may be considered a reference implementation because no other implementations are correct.
import sys,math
from collections import defaultdict
# The only standards-compliant implementation of Vague
class Vague:
def __init__(self,program):
self.program = program
self.pc=0
self.jump=1
self.data=""
self.copymode = False
self.stackmode = False
self.stack = []
self.commands = defaultdict(self.nop,{'+': self.add,
'-': self.dec,
'!': self.output,
'>': self.right,
'<': self.left,
'&': self.nand,
'=': self.push,
'_': self.pop,
'.': self.end,
'0': self.zero,
'*': self.discouraged,
'2': self.to2D,
'1': self.to1D,
't': self.copyon,
'f': self.copyoff,
'(': self.start,
')': self.endp
})
def nop(self):
return self.nop
def step(self):
if self.copymode: self.program += self.program[self.pc]
self.commands[self.program[self.pc]]()
self.pc+=self.jump
def run(self):
while 0<=self.pc<len(self.program):
self.step()
def output(self):
if isinstance(self.data,str):
sys.stdout.write(self.data)
else:
print()
for x in self.data:
print(x)
def to2D(self):
if isinstance(self.data,str):
n = max(1,int(math.sqrt(len(self.data))))
self.data=[self.data[i:i+n] for i in range(0, len(self.data), n)]
def to1D(self):
if isinstance(self.data,list):
self.data = "".join(self.data)
def add(self):
if self.stackmode:
if len(self.stack)>=8:
num=0
for i in "*"*8:
bit = int(self.stack.pop())
num = 2*num+bit
if isinstance(self.data,str):
self.data += chr(num)
else:
self.to1D()
self.data += chr(num)
self.to2D()
else:
newdata = input()
if isinstance(self.data,str):
self.data += newdata
else:
self.to1D()
self.data += newdata
self.to2D()
def right(self):
self.jump+=1
def left(self):
self.jump-=1
def discouraged(self):
for i,b in enumerate(self.stack):
if b and i<len(self.data):
self.program+=self.data[~i]
def copyon(self):
if self.stackmode:
self.stack.append(True)
else:
self.copymode = True
def copyoff(self):
if self.stackmode:
self.stack.append(False)
else:
self.copymode = False
def dec(self):
if self.stackmode:
self.stack.pop(0)
else:
self.data = self.data[:-1]
def zero(self):
if self.stackmode:
self.stack=[]
else:
self.data=""
def push(self):
if self.stackmode:
last = self.data[-1][-1]
num = ord(last)
for i in "*"*8:
self.stack.append(bool(num%2))
num//=2
else:
if isinstance(self.data,str):
if 0<=self.pc+self.jump<len(self.program):
self.data += self.program[self.pc+self.jump]
self.pc+=self.jump
else:
if 0<=self.pc+self.jump<len(self.program):
self.data += self.program[self.pc+self.jump:self.pc+selfjump*len(self.data[0])+1:self.jump]
self.pc+=len(self.data[-1]*self.jump)
def pop(self):
if self.stackmode:
self.stack.pop()
else:
self.data = self.data[1:]
def start(self):
self.stackmode = True
def endp(self):
self.stackmode = False
def nand(self):
if self.stackmode:
if len(self.stack)>=2:
b = self.stack.pop()
self.stack.append(not (self.stack.pop() and b))
else:
self.pc = len(self.program)+~(self.pc&ord(self.data[-1][-1]))
def end(self):
if self.stackmode:
if len(self.stack)>=2:
self.stack[-2:]=self.stack[:-3:-1]
else:
self.pc=len(self.program)-1-self.jump
if __name__=="__main__":
if len(sys.argv)<2:
print("No filename to execute.")
else:
try:
with open(sys.argv[1], "r") as f:
listing = f.read()
p = Vague(listing)
p.run()
except IOError: print("File '"+filename+"' not found."); sys.exit(1)