FourQueue/Interpreter.py

From Esolang
Jump to navigation Jump to search
Back to FourQueue
from collections import deque
import sys, re, random, argparse

def Err44():
    sys.stderr.write("ERROR 44")
    sys.exit(1)

def FourQueue(prgm, inp, no_prng, any_ints):
    if not any_ints and not re.search('^[4 ]*$', prgm):
        Err44()
    
    numQueue = deque()
    progStack = [*map(int, prgm.split())][::-1]
    
    if no_prng:
        x, y = 7, 8
    else:
        x = random.randint(7, 99)
        y = random.randint(7, 99)
        while x == y or x == 44 or y == 44:
            x = random.randint(7, 99)
            y = random.randint(7, 99)
    
    while progStack:
        cmd = progStack.pop()
        if cmd == 0:
            sys.exit(0)
        elif cmd == 1:
            if len(numQueue) < 2: Err44()
            a = numQueue.popleft()
            b = numQueue.popleft()
            numQueue.append(a + b)
        elif cmd == 2:
            if len(numQueue) < 2: Err44()
            a = numQueue.popleft()
            b = numQueue.popleft()
            numQueue.append(a - b)
        elif cmd == 3:
            if len(numQueue) < 2: Err44()
            a = numQueue.popleft()
            b = numQueue.popleft()
            numQueue.append(a * b)
        elif cmd == 4:
            if len(numQueue) < 2: Err44()
            a = numQueue.popleft()
            b = numQueue.popleft()
            if b != 0:
                numQueue.append(a // b)
            else:
                progStack.append(a)
        elif cmd == 5:
            if len(numQueue) == 0: Err44()
            a = numQueue.popleft()
            if a not in range(0x110000): Err44()
            print(chr(a), end='')
        elif cmd == 6:
            if inp:
                numQueue.append(ord(inp[0]))
                inp = inp[1:]
            else:
                numQueue.append(-1)
        elif cmd == x:
            if len(numQueue) == 0: Err44()
            a = numQueue.popleft()
            seq = []
            if len(numQueue) < a: Err44()
            for i in range(a):
                seq.append(numQueue.popleft())
            progStack.extend(seq[::-1])
        elif cmd == y:
            if len(numQueue) < 2: Err44()
            a = numQueue.popleft()
            b = numQueue.popleft()
            seq = []
            if len(numQueue) < a: Err44()
            for i in range(a):
                seq.append(numQueue.popleft())
            for i in range(b):
                for n in seq:
                    numQueue.append(n)
        elif re.search('^44+$', str(cmd)):
            numQueue.append(cmd // 10)
        else:
            numQueue.append(cmd)

salt = ['fjords', 'jawbox', 'phlegm', 'qiviut', 'zincky']
random.shuffle(salt)
opt1 = '--no-prng-' + '-'.join(salt)
random.shuffle(salt)
opt2 = '--any-ints-' + '-'.join(salt)

try:
    parser = argparse.ArgumentParser(description='Run a FourQueue program')
    parser.add_argument('progtorun', metavar='progtorun', type=str,
        help='the filename of the FourQueue program to run')
    parser.add_argument(opt1, dest='no_prng', action='store_true',
        help='guarantee x=7 and y=8')
    parser.add_argument(opt2, dest='any_ints', action='store_true',
        help='allow any integers in the source code')
    args = parser.parse_args()
    
    f = open(args.progtorun)
    prgm = f.read()
    f.close()
    inp = input('Input: ')
    FourQueue(prgm, inp, args.no_prng, args.any_ints)
except IOError:
    sys.stderr.write("Error: Can't open file '%s'" % args.progtorun)
    sys.exit(1)