ACIDIC
ACIDIC is an esoteric programming language made by User:iconmaster.
Syntax
It consists of two rows of commands, which usually looks like gibberish to human eyes. There are no invalid ASCII characters, most are used in commands. Here is what a program may look like:
‘m!g&hQWs #45.HkjdQ~
Please note that this program is not supposed to work.
The first row is always the Storage Stack, which contains data. Below that is the Command Stack, which actually runs your program. Not seen here is the Accumulator, or A, and the Auxiliary Accumulator, or B. These are set by instructions in the Command Stack. Both A and B start at 0. The computer turns each character into a command, working right to left, until the pointer is less than 0. It then starts back at the beginning (end?) until the Command Stack is size 0 or a BRK instruction is met. This language has no system of comments, as the entire program is a large comment on the programmer’s state of mind.
This language is limited by the fact that you cannot create new characters for either stack.
Commands
PUSH 3 F Y l pushes the leftmost value of the Storage Stack onto the Command Stack. POP ! 4 G Z m pops the value to the left of it onto the Storage Stack ROT " 5 H [ n rotates the Storage Stack once to the right. INC # 6 I \ o Increments A. DEC $ 7 J ] p Decrements A. JUMP % 8 K ^ q jumps to the command pointed to by A (starting at the left, of course). STKSZE & 9 L _ r makes A equal to the size of the Storage Stack. JMPR ' : M ` s Jumps A paces to the left. PUSHR ( ; N a t pushes the value at A on the Storage Stack onto the Command Stack. POPR ) < O b u pops the command at A onto the Storage Stack. OUTPUT * = P c v Displays the Storage Stack. BRK + > Q d w Ends the program. EXC , ? R e x Exchanges B with A. INPUT - @ S f y sets A to the value at STDIN. RPLC . A T g z Replaces this command with a command in the Storage Stack in the same column. ROTA / B U h { rotates the Storage Stack A times to the right. JMPZ 0 C V i | jumps to the command pointed to by A if B is equal to 0 JMPNZ 1 D W j } jumps to the command pointed to by A if B is not equal to 0 PLC 2 E X k ~ sets A to the current pointer position.
Examples
This program will display the immortal words “Hello, world!”
Hello, world! wP
This version is better:
wPH!e!l!l!o!,! !w!o!r!l!d!!!
Implementation
Here is an interpreter, written in C#. It sets A to -1 on EOF, and assumes that the first two lines of input are the program and data.
using System; using System.Collections.Generic; using System.Linq; class ACIDIC { static void Main() { int a = 0, b = 0, temp = 0; List<char> data = Console.ReadLine().ToCharArray().ToList(), prog = Console.ReadLine().ToCharArray().ToList(); for (int i = prog.Count - 1; ; i--) if (i < 0) i = prog.Count; else switch (prog[i]) { case ' ': case '3': case 'F': case 'Y': case 'l': if (data.Count == 0) continue; prog.Insert(0, data[0]); data.RemoveAt(0); i++; break; case '!': case '4': case 'G': case 'Z': case 'm': if (i == 0) continue; data.Insert(0, prog[i - 1]); prog.RemoveAt(i - 1); i--; break; case '"': case '5': case 'H': case '[': case 'n': data.Insert(0, data[data.Count - 1]); data.RemoveAt(data.Count - 1); break; case '#': case '6': case 'I': case '\\': case 'o': a++; break; case '$': case '7': case 'J': case ']': case 'p': a--; break; case '%': case '8': case 'K': case '^': case 'q': if (a < 0 || a >= prog.Count) continue; i = a + 1; break; case '&': case '9': case 'L': case '_': case 'r': a = data.Count; break; case '\: case ':': case 'M': case '`': case 's': if (a > i) continue; i -= a - 1; break; case '(': case ';': case 'N': case 'a': case 't': if (a < 0 || a >= data.Count) continue; prog.Insert(0, data[a]); data.RemoveAt(a); if (a <= i) i++; break; case ')': case '<': case 'O': case 'b': case 'u': if (a < 0 || a >= prog.Count) continue; data.Insert(0, prog[a]); prog.RemoveAt(a); if (a <= i) i--; break; case '*': case '=': case 'P': case 'c': case 'v': Console.Write(String.Concat(data)); break; case '+': case '>': case 'Q': case 'd': case 'w': return; case ',': case '?': case 'R': case 'e': case 'x': temp = a; a = b; b = temp; break; case '-': case '@': case 'S': case 'f': case 'y': a = Console.Read(); break; case '.': case 'A': case 'T': case 'g': case 'z': if (data.Count <= i) continue; prog[i] = data[i]; break; case '/': case 'B': case 'U': case 'h': case '{': if (data.Count == 0) continue; for (int j = 0; j < a; j++) { data.Insert(0, data[data.Count - 1]); data.RemoveAt(data.Count - 1); } break; case '0': case 'C': case 'V': case 'i': case '|': if (a < 0 || a >= prog.Count || b != 0) continue; i = a + 1; break; case '1': case 'D': case 'W': case 'j': case '}': if (a < 0 || a >= prog.Count || b == 0) continue; i = a + 1; break; case '2': case 'E': case 'X': case 'k': case '~': a = i; break; } } }
Fleeting Thoughts
- ACIDIC was named so because in chemistry, the opposite of a base is an acid. Since BASIC is an easy language, ACIDIC is a hard one.
- ACIDIC is suspected to be Turing-Incomplete, but theoretically, since A and B can have an infinite value, ACIDIC could possibly run a Minsky machine.
- The Storage Stack and the Command Stack are not actually stacks; they're more like linked lists. They were named so to increase confusion.
- The 5 symbols each command is mapped to is based on successive ASCII characters; starting from " ", going down and then right in the command list, and ending at "~".
- Meaningful output is nigh impossible because A) you can only output the Storage Stack and B) you can't create new characters for either stack.
See Also
- Cyclic ACIDIC, a derivative of ACIDIC