Aura

From Esolang
Jump to navigation Jump to search

Aura is an esoteric programming language invented by Jamie Aczel. It is inspired by Brainfuck, but its logic is more like Malbolge.

Aura has no independent data space, forcing it to store data in the command space: all operators spew their output into the very next instruction. There are no jump commands; the program continues until it meets a "reverse program flow" instruction.

Description

The following has been deduced from the code of the interpreter. Apparent debugging output has been ignored. The interpreter has a 5000 byte memory limit, which seems inessential.

Memory is initialized to a zero-terminated string containing the program's byte characters. The initialization is not portable because it depends on character sign conventions: reading stops at the first non-positive character (it might even ignore EOF on some systems).

For reasonably portable results, programs should contain only bytes 1-127, except for a single 0 at the end.

The execution always begins at the third character, with program flow going rightwards. Three-character programs are the smallest possible programs that are really executed. In two-character programs the interpreter starts executing the terminating zero, which immediately terminates the program.

If execution reaches either end of the program, undefined behavior may arise, as a result of memory access beyond the program boundary. After executing the end instruction, the program counter wraps to the other side. This happens before the normal increment/decrement of the program counter. If the end instruction was a program flow reversal, program flow may escape the program boundary, giving further undefined behavior.

Bytes are interpreted as commands according to their value modulo 8. Below "the next byte" means the next byte in the current program flow direction.

(mod 8) command description
0 If the current byte is exactly 0, exit the program. Otherwise, divide the next byte by the current one. Non-portable: Result may depend on the sign conventions of characters and division.
1 Subtract the current byte from the next one.
2 Decrement the next byte.
3 Read an input character and add it to the next byte.
4 Reverse program flow.
5 Print the previous byte as a character if it is printable (dependent on locale). Increment the next byte.
6 Add the current byte to the next one.
7 Multiply the next byte by the current one.

Computational class

Aura cannot be Turing-complete, as there is no way to safely grow memory. Determining Aura's actual computational class poses an intriguing open question. Since all operations immediately modify the program, it is unclear whether it is possible to cause an arbitrary effect at an arbitrary point.

Some program strings, for example "446" can manage to escape the program boundary and grow until they exhaust the interpreter's fixed size array. The program "446" works the following way (x behind a character marks where the instruction pointer is currently at):

4 4x 6 ; The interpreter begins at the second "4", increases the instruction pointer,
       ; and thus gets to the next instruction, without executing "4".

4 4 6x ; The character 2 ("6") is the first that is executed.
       ; The next cell (cell 3, which is initially 0) will get character "6" to its value.

       ; In the next cycle the interpreter checks if the instruction pointer is x.
       ; (x is the length of the program, measured before starting execution, and never changed after.)
       ; The instruction pointer is not at 3 (which x is in this case) but in 2.
       ; The instruction pointer is incremented, and thus set to 3.

4 4 6 6x ; The "6" is executed and the next cell will get character "6" to its value.
         ; In the next cycle the IP is equal to x (3 in this case), and the IP is thus
         ; moved to 0. Then it's incremented, and ends up to 1.

4 4x 6 6 6 ; The direction of the pointer is changed there. On the next cycle
           ; the IP is decremented (as the direction is different now), and it ends up
           ; to the cell 0.

4x 4 6 6 6 ; In cell 0 the direction is changed again. On the next cycle the interpreter
           ; finds out the IP is at cell 0, and thus sets it to x (3). Then it's incremented,
           ; as always in the beginning of cycle, and it ends up to 4.

4 4 6 6 6x ; The next 0 cell will get character "6" to its value. The pointer is moved one forward.

4 4 6 6 6 6x ; Same as above. A pattern has started.

4 4 6 6 6 6 6x ; And so forth.

External resources