Affine Mess

From Esolang
Jump to navigation Jump to search

Affine Mess is an esoteric programming language created by User:Caenbe. Its purpose is to explore what is possible when the programmer can use XOR and NOT freely, but can't use AND except where the language allows. How well it accomplishes that purpose is debatable, because the programmer is also hindered by the fact that there are only 25 bits in the memory. Despite this, some popular problems are possible (with some caveats). There may be another language in the future based on this one which implements infinite memory. This language is inspired by XOṘ Mạchịne. Like that language, the only command is the XOR command. I/O and AND operations are memory mapped, and the entire program runs in an implicit loop.

Syntax

The lowercase letters of the Latin alphabet (excluding l) represent the 25 bits. 1 represents the constant bit 1. Every pair of bit names, e.g. ab, is a command which computes a XOR b and stores the result in a. 11 is used to open and close comments.

Program Flow

These are the steps taken to execute a program. Note: bytes are represented most significant bit first.

  1. All bits are initialized to 0.
  2. A byte from the input stream is stored in i-q. If none is available, 0s are used.
  3. All XOR commands in the program are run.
  4. The byte r-y is sent to the output.
  5. The bitwise AND of a-h and i-q is stored in r-y.
  6. If z==1, terminate. Otherwise, return to step 2.

Examples

Truth-machine:

zm zq t1 u1 y1 yz

Hello World: (Actually prints "Hi World")

11
   Sliding memory. A single 1 starts at a, and slides to h, where it causes the program to halt.
11

hggg zh gfff feee eddd dccc cbbb baaa abacadaeafagaha1

11
   Print 'Hi World'
11

   sa       va
   sb tb    vb       yb
      tc
   sd    ud    wd xd yd
   se te    ve we xe ye
   sf tf uf       xf
   sg tg    vg wg
   sh th       wh

Cat program: (Note: 4 null characters are printed after the input is echoed)

aa bb cc dd ee ff gg hh
ai bj ck dm en fo gp hq
ii jj kk mm nn oo pp qq
ir js kt mu nv ow px qy
rr ss tt uu vv ww xx yy
ra sb tc ud ve wf xg yh

a1 b1 c1 d1 e1 f1 g1 h1
eiieei fjjffj gkkggk hmmhhm
gnnggn hoohho hpphhp zh

Interpreter

Written in Python 3.

# Affine Mess Interpreter
# Author: Caenbe
# Version 0.2

import sys, os

CMDS = "abcdefghijkmnopqrstuvwxyz1"

def main():
    
    filename = input("File name: ") # Ask the user for the file to run
    f = open(os.path.join(sys.path[0], filename), "r")
    program = f.read()
    f.close()
    
    p = ''.join(program.split('11')[::2]) # Remove comments
    
    # Translate every command to a number
    instructions = list(filter(lambda x: x > -1, map(lambda c: CMDS.find(c), p)))
    
    print("Program read!")
    # Get input (this is done before execution, because getting input during would be annoying)
    prgmInput = input("Supply input: ")
    inputIndex = 0
    
    memory = [False] * 25
    midInstruction = False
    
    while (not memory[24]): # While the halt flag (z) is not set
        nextChar = chr(0)
        if (inputIndex < len(prgmInput)):
            # Input a character
            nextChar = prgmInput[inputIndex]
            inputIndex = inputIndex + 1
        charIntoBoolList(nextChar, memory, 8)
        
        firstHalf = 0
        for inst in instructions:
            if (not midInstruction):
                # If this is the first half of an instruction, remember it
                firstHalf = inst
                midInstruction = True
            else:
                if (inst == 25):
                    memory[firstHalf] = not memory[firstHalf] # XOR a variable with 1 (i.e. toggle it)
                else:
                    memory[firstHalf] = (memory[firstHalf] != memory[inst]) # XOR two variables together
                midInstruction = False
        
        print(charFromBoolList(memory, 16), end='') # Output a character
        
        for i in range(8):
            memory[i + 16] = memory[i] and memory[i + 8] # AND operation

# Utility function that puts a character into memory
def charIntoBoolList(ch, boolList, start):
    nextChar = int(ord(ch))
    for i in range(8):
        boolList[start + 7 - i] = (nextChar % 2 == 1)
        nextChar = int(nextChar / 2)

# Utility function that extracts a character from memory
def charFromBoolList(boolList, start):
    outChar = int(0)
    for i in range(8):
        outChar = outChar * 2
        if boolList[start + i]:
            outChar = outChar + 1
    return chr(outChar)
                
if __name__ == '__main__':
    main()