Vague/Quintopia

From Esolang
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)