Bauberqueue/bauberqueue.py

From Esolang
Jump to navigation Jump to search

Reference implementation for Bauberqueue in Python.

import sys
from collections import defaultdict

def load(filename):
    try: 
        listing = defaultdict(list)
        with open(filename, "r") as openfile:
            for num,line in enumerate(openfile):
                listing[num+1] = map(ord,list(line.rstrip().decode('string_escape')))
    except IOError: print("File '%s' not found."%filename); sys.exit(1)
    return listing

def get(data,id):
    if id==ord("1"):
        return 1
    if id in map(ord,"abi"):
        return data.__dict__[chr(id)]
    if id in map(ord,"ABI"):
        return data.listing[data.__dict__[chr(id+32)]].pop(0) if data.listing[data.__dict__[chr(id+32)]] else 0
    if id==ord("o"):
        return ord(sys.stdin.read(1))        #blocks and waits for an input if buffer empty, reads 1 byte
    try: id = chr(id)
    except ValueError: 
        try: id = unichr(id)
        except ValueError: id = str(id)
    raise ValueError(id + "is an invalid source argument in queue %d."%data.i)

def put(data,id,val):
    if id in map(ord,"abi"):
        data.__dict__[chr(id)]=val
    elif id in map(ord,"ABI"):
        data.listing[data.__dict__[chr(id+32)]].append(val)
    elif id==ord("o"):
        try: sys.stdout.write(chr(val))
        except ValueError: 
            try: sys.stdout.write(unichr(val))
            except ValueError: pass
    else:
        try: id = chr(id)
        except ValueError: 
            try: id = unichr(id)
            except ValueError: id = str(id)
        raise ValueError(id + " is an invalid target argument in queue %d."%data.i)

def run(data):
    while True:
        x,y,z=[data.listing[data.i].pop(0) if data.listing[data.i] else 0 for _ in range(3)]
#        print chr(x),chr(y),chr(z)
#        import pdb;pdb.set_trace()
        if (z==ord("o") or y==ord("o")) and x!=ord('='):
            raise ValueError('o used as source or target of non-assignment command at queue %d.'%data.i)
        if x==ord("="):
            put(data,y,get(data,z))
        elif x==ord("+"):
            put(data,y,get(data,y)+get(data,z))
        elif x==ord("-"):
            put(data,y,get(data,y)-get(data,z))
        elif x in map(ord,"abiABI"):
            count=get(data,z)
            seq = []
            src = get(data,y)
            tgt = get(data,x)
            for c in range(count):
                seq.append(data.listing[src].pop(0) if data.listing[src] else 0)
            data.listing[tgt].extend(seq*2)
        else:
            break
        data.listing[0]=[] #throw out the trash

if __name__=="__main__":
    class Aubergine:
        def __init__(self, listing, a, b, i): 
            self.listing = listing
            self.a = a
            self.b = b
            self.i = i
    if len(sys.argv)<2:
        print "No filename to execute."
    else:
        listing = load(sys.argv[1])
        data = Aubergine(listing, 0, 0, 1)
        try:
            run(data)
        except Exception as e:
            print e.message
            for key in data.listing.keys():
                if key!=0:
                    print key,map(chr,data.listing[key])
            print "a",data.a
            print "b",data.b
            print "i",data.i