ABCDXYZ/Python interpreter

From Esolang
Jump to navigation Jump to search
Back to ABCDXYZ

The esolang ABCDXYZ had no real interpreter before 2024 (previous implementations were all transpilers to another language). As such, User:None1 created the first real interpreter for ABCDXYZ on June 15th 2024. It is written in Python. (Due to Python's recursion limit, the call stack cannot be longer than 1000, you can change the recursion limit using sys.setrecursionlimit), you can also see this program at Pastebin.

# First real interpreter for ABCDXYZ, in Python, by User:None1
# Usage: python abcdxyz.py <filename>
import sys
call_stack=[]
objects=[]
class ABCDXYZ:
    data=0
    def __init__(self,event,num):
        self.event,self.num=event,num
    def x(self,num):
        t=objects[num].data
        objects[num].data=[1,2,3,0][objects[num].data]
        if t==1:
            objects[num].fire()
    def y(self,num):
        t=objects[num].data
        objects[num].data=[1,2,3,0][objects[num].data]
        if t==2:
            objects[num].fire()
    def z(self,num):
        if objects[num].data:
            objects[num].data=[0,3,1,2][objects[num].data]
    def fire(self):
        global call_stack
        if self.num in call_stack:
            raise RecursionError('Recursion is forbidden')
        call_stack.append(self.num)
        for i in self.event:
            if i[0]=='"':
                if len(i)!=2 or i[1] not in '0123456789N':
                    raise SyntaxError('" must be followed by digits or N')
                else:
                    print('\n' if i[1]=='N' else i[1],end='')
            elif i[0]=='X':
                try:
                    num=int(i[1])
                except:
                    raise SyntaxError('X must be followed by a number')
                else:
                    self.x(num)
            elif i[0]=='Y':
                try:
                    num=int(i[1])
                except:
                    raise SyntaxError('Y must be followed by a number')
                else:
                    self.y(num)
            elif i[0]=='Z':
                try:
                    num=int(i[1])
                except:
                    raise SyntaxError('Z must be followed by a number')
                else:
                    self.z(num)
            else:
                raise SyntaxError('Unknown command: {}'.format(i))
        call_stack.pop()
with open(sys.argv[1],'r') as f:
    c=f.read().split()
n=0
e=[]
if c[0]!=str(n)+':':
    SyntaxError('Cannot find object 0')
del c[0]
while c:
    n+=1
    while c and c[0]!=str(n)+':':
        e.append(c[0])
        del c[0]
    if c:
        del c[0]
    objects.append(ABCDXYZ(e,n-1))
    e=[]
objects[0].fire()

Looks very object oriented, doesn't it?