|Computational class||Turing complete|
Emanator is an esolang invented by User:Hakerh400 in 2023.
Source code consists of integers separated by dots.
Memory consist of a single tape, which can be represented as a function . All cells are initially , except the cells at addresses , which contain the source code, where is the length of the source code. Here, by source code we mean the list of integers parsed from the source code and not the literal source code string.
Memory contains the entire program state. There are no external registers such as instruction pointer or data pointer.
If we want to access cell at address , then there are two cases:
- If , then we access cell directly.
- Otherwise, let be the value from cell . The result of accessing is the result of accessing . If accesses form a loop, then we either read from input (if we want to read a value), or write to the output (if we want to write a value).
Perform the following algorithm until the program outputs number . Let
ip be the value from cell . Let
dest be the value from cell
ip (keep in mind indirect addressing explained above). Let
op1 be the value from cell
ip + 1 and
op2 be the value from cell
ip + 2. Write value
ip + 3 to cell and then write value
op1 - op2 to cell
If anything in this explanation is unclear, see the implementation for details.
Explanation. The cell contains value . It represents the initial value of
ip (instruction pointer).
Each "instruction" is 3 cells long. Our first instruction is
-4 -5 1. In pseudocode it means
mem[-4] = mem[-5] - mem. Of course, since memory contains only positive addresses, and represent indirect addressing, so we are effectively addressing and , respectively. However, since
mem = -4 and
mem = -5, we have a cycle in both cases. We first evaluate operands, so
mem[-5] resolves to the next character code from the input string. The second operand
mem directly resolves to
0. The result is
C - 0 = C, where
C is the next character code from the input (because the indirect addressing formed a cycle at
mem[-5]). Finally, since
mem[-4] also forms a cycle, we output the result
C directly to the output stream.
Instruction pointer gets incremented by , so it becomes . The next "instruction" is
0 2 1. It means
mem = mem - mem = 3 - 0 = 3, so we write value to the instruction pointer, effectively jumping back to the first instruction. We perform these steps until we read integer (the end of input stream) and output it, which terminates the program.
This language is Turing-complete. We leave to the readers to figure out why.