Design goal: To create a programming language using primarily the Miscellaneous Symbols Unicode characters (U+2600 through U+26FF). Also used are Enclosed Alphanumerics (starting at U+2460) and Dingbats (starting at U+2700). No ASCII is used except whitespace. It also happens to be fairly difficult to program in, moreso than my other languages.
General format of program
A program consists of a sequence of instructions and labels, most of which are one character long. There are one accumulator, four special-purpose stacks, and twenty-six general-purpose variables, all described below.
All whitespace in the program (including newlines) is ignored. The parenthesized alphanumerics ⑴-⒇,and ⒜-⒵ (U+2474 through U+2487 and U+249C through U+24B5) are also ignored, and can be used to add comments to the program.
The accumulator stores a single non-negative integer.
♮ (U+266E MUSIC NATURAL SIGN)
Sets the accumulator to zero
♯ (U+266F MUSIC SHARP SIGN)
Adds 1 to the accumulator
♭ (U+266D MUSIC FLAT SIGN)
Jump to next ☂ if accumulator is zero; otherwise, subtract 1 from accumulator
♙, ♘, ♗, ♖, ♕, ♔ (U+2659 WHITE CHESS PAWN through U+2654 WHITE CHESS KING)
Multiply accumulator respectively by 2, 3, 5, 7, 11, 13
♟, ♞, ♝, ♜, ♛, ♚ (U+265F BLACK CHESS PAWN through U+265A BLACK CHESS KING)
Jump to next ☂ if accumulator is not divisible by n; otherwise, divide accumulator by n, where n = 2, 3, 5, 7, 11, 13, depending on the symbol used
⚀, ⚁, ⚂, ⚃, ⚄, ⚅ (U+2680 DIE FACE-1 through U+2685 DIE FACE-6)
Sets the accumulator to a random number between zero and the number shown on the die, inclusive
☂ (U+2602 UMBRELLA)
Label for error handler. Control will jump here if the accumulator tries to become negative or fractional (in which case the accumulator will be the same as what it was before the offending instruction). Control may also jump here for any other error (depending on the implementation); if that happens, the current state is undefined. If there is no umbrella after a statement with an error, it acts as if there is one at the end of the program.
☀ (U+2600 BLACK SUN WITH RAYS)
Modifier for ☂. If there is a sunshine between an operation that causes an error and the umbrella it would otherwise jump to, rather than jumping to the umbrella, it will simply continue to the next statement.
Like many programming languages, Symbols has an unconditional jump instruction, and keeps track of jumps on a stack so that calls may return to the caller. However, unlike most other programming languages, there are different sets of commands for forward ("black") and backward ("white") jumps, and there are two separate call stacks as well.
⚐ (U+2690 WHITE FLAG)
Label for a white (backward) jump.
☏ (U+260F WHITE TELEPHONE)
Push the next instruction to the white call stack, jump to the previous ⚐ (or the beginning of the program if there is no such label).
♡ (U+2661 WHITE HEART SUIT)
Pop the white call stack and return if the accumulator is at least 3. Does nothing if the accumulator is less than three.
⚑ (U+2691 BLACK FLAG)
Label for a black (forward) jump.
☎ (U+260E BLACK TELEPHONE)
Push the next instruction to the black call stack, jump to next ⚑ (or the end of the program if there is no such label).
♥ (U+2665 BLACK HEART SUIT)
Pop the black call stack and return if the accumulator is at least 3. Does nothing if the accumulator is less than three.
☯ (U+262F YIN YANG)
Pop both call stacks, discarding their values.
If an attempt is made to pop a stack that is empty (including with ☯), the result is undefined.
Arrays and pointers
The only type of data that can be stored in a variable is an array. The only type of element that an array can have is an array. The standard way to store a number is as the length of an array. All arrays must be manually allocated and deallocated except for empty (zero-length) arrays. There is a stack called the pointer stack, which pointers arrays can be pushed onto; however, an array must be in a variable to get an element from it or query its size. The commands for doing so are described in the next section.
✎ (U+270E LOWER RIGHT PENCIL)
Allocates an array of pointers, with the size specified by the accumulator, and pushes it onto the pointer stack. All elements are initialized to the empty array.
♲ (U+2672 UNIVERSAL RECYCLING SYMBOL)
Pops a pointer from the pointer stack and frees the memory associated with it. Does nothing if the pointer points to the empty array. Any attempts to access the memory or free it again result in undefined behavior.
There are twenty-six variables, A through Z, that store pointers to arrays. All variables initially point to the empty array.
Access to variables is controlled by the subscript stack, a stack that can hold non-negative integers and a special value called a mark. If the subscript stack is not empty when a variable is accessed, each element of the subscript stack will be popped and the current array subscripted (first element is zero) until a mark (or the bottom of the stack) is reached; the mark is also popped. For instance, if 2, 3, mark, 4, 5 are pushed onto the stack, and the variable A is accessed using any command, that command will actually work on A, and the subscript stack will become 2, 3.
☃ (U+2603 SNOWMAN)
Push the value of the accumulator onto the subscript stack
☁ (U+2601 CLOUD)
Push a mark onto the subscript stack
Ⓐ-Ⓩ (U+24B6 through U+24CF CIRCLED LATIN CAPITAL LETTER A-Z)
Set the accumulator to the size of the array.
ⓐ-ⓩ (U+24D0 through U+24E9 CIRCLED LATIN SMALL LETTER A-Z)
Pop the pointer stack, set the variable to the pointer's value.
✂Ⓐ-Ⓩ (U+2702 BLACK SCISSORS followed by U+24B6 through U+24CF CIRCLED LATIN CAPITAL LETTER A-Z)
Push the value of the current variable to the pointer stack.
☢ⓐ-ⓩ (U+2622 RADIOACTIVE SIGN followed by U+24D0 through U+24E9 CIRCLED LATIN SMALL LETTER A-Z)
Recursively frees everything in the specified array (including the array itself) and sets the variable to the empty array.
Input and output
❝ (U+275D HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT)
Reads one line of input; allocates a new array, and adds arrays to it indicating the Unicode values of the characters read. The newline character is not included; however, the null terminator is. The array is pushed onto the pointer stack. The program should set the accumulator to zero before this instruction for future compatability.
❞ (U+275E HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT)
Pops the pointer stack, interprets the length of each array as a Unicode value, and displays the string. Stops if it reaches an empty array. The program should set the accumulator to zero before this instruction for future compatability.