On this page:
Bespoke is a stack-based esoteric programming language whose instructions are encoded in the letter-counts of ordinary words. The language supports arbitrary-precision integers, a stack, a heap, conditionals, loops, and functions — all expressed through natural prose.
Encoding
Before a Bespoke program runs, its words are converted to digits:
- Only alphabetic characters and apostrophes (' or ') count as part of a word. All other characters act as word separators.
- An n-letter word produces:
- The digit n if n < 10
- The digit 0 if n = 10
- Two consecutive digits if n > 10 (e.g. a 12-letter word → 1 2)
- Apostrophes do not count towards a word's length: couldn't → 7 letters → digit 7.
Examples:
| Word(s) | Digit(s) |
|---|---|
| I | 1 |
| tiny | 4 |
| pythons | 7 |
| vocabulary | 0 |
| couldn't | 7 |
| unintelligible | 1, 4 |
| I marred a groaning silhouette | 1, 6, 1, 8, 0 |
Data Model
Bespoke works with arbitrary-precision integers — there is no limit on how large or negative a number can be. Values live in one of two places:
- The stack — a last-in, first-out sequence. Numbers are pushed onto and popped from the top.
- The heap — a mapping from integer addresses to integer values. Any integer is a valid address; unset addresses default to 0.
Mnemonics
The documentation uses a set of "mnemonic" words to describe instructions. Any word of the correct length produces the same digit — the actual words shown below are just illustrative. The digit-to-mnemonic map for numeric arguments is:
| Digit | Mnemonic |
|---|---|
| 1 | I |
| 2 | BI |
| 3 | TRI |
| 4 | FOUR |
| 5 | FIFTH |
| 6 | SEXTET |
| 7 | SEVENTH |
| 8 | INTEIGHT |
| 9 | DIGITNINE |
| 0 | NUMBERZERO |
So PUSH SEVENTH encodes the digit sequence 47, which pushes 7 onto the stack — but tiny pythons (4 + 7) does exactly the same thing.
Instructions
Instructions are identified by the first digit of a two-digit sequence (or sometimes a longer sequence for multi-digit numbers). There are 10 categories.
1 — H (Heap)
| Sequence | Mnemonic | Effect |
|---|---|---|
| 11 / 13 / 15 / 17 / 19 | H V / H LDV / … | Pop addr from stack; push the value at heap[addr] (0 if unset). |
| 12 / 14 / 16 / 18 / 10 | H SV / H STRV / … | Pop addr then val from stack; store val at heap[addr]. |
2 — DO (Stack manipulation)
| Sequence | Mnemonic | Effect |
|---|---|---|
| 21 | DO P | Pop and discard the top value. |
| 22 | DO PN | Pop n; remove the nth value from the top (negative = from bottom). |
| 23 | DO ROT | Pop n; rotate the top value down to the nth position. |
| 24 | DO COPY | Duplicate the top value. |
| 25 | DO COPYN | Pop n; copy the nth value to the top. |
| 26 | DO SWITCH | Swap the top two values. |
| 27 | DO SWITCHN | Pop n; swap the top value with the nth. |
| 28 | DO TURNOVER | Reverse the entire stack. |
| 29 | DO TURNOVERN | Pop n; reverse the top n values. |
| 20 | DO ROTINVERSE | Pop n; rotate the nth value up to the top. |
For commands that take n: a positive n counts from the top; a negative n counts from the bottom. n cannot be 0.
3 — PUT (push multi-digit number)
PUT pushes a number with up to 10 digits onto the stack. The digit immediately after 3 specifies how many digits the number has (0 = 10), followed by those digits.
| Sequence | Mnemonic | Pushes |
|---|---|---|
| 315 | PUT X:FIFTH | 5 |
| 3210 | PUT XX:I NUMBERZERO | 10 |
| 33123 | PUT XXX:I BI TRI | 123 |
| 3516180 | PUT XXXXX:I SEXTET I INTEIGHT NUMBERZERO | 16180 |
4 — PUSH (push single-digit number)
The digit after 4 is the number pushed (0–9).
| Sequence | Mnemonic | Pushes |
|---|---|---|
| 42 | PUSH BI | 2 |
| 47 | PUSH SEVENTH | 7 |
| 40 | PUSH NUMBERZERO | 0 |
5 — INPUT
| Sequence | Mnemonic | Effect |
|---|---|---|
| 51 / 53 / 55 / 57 / 59 | INPUT N / INPUT INT / … | Read a number from input; push it. |
| 52 / 54 / 56 / 58 / 50 | INPUT CH / INPUT CHAR / … | Read one character; push its Unicode codepoint. Push -1 on EOF. |
6 — OUTPUT
| Sequence | Mnemonic | Effect |
|---|---|---|
| 61 / 63 / 65 / 67 / 69 | OUTPUT N / OUTPUT INT / … | Pop n; output it as a decimal number. |
| 62 / 64 / 66 / 68 / 60 | OUTPUT CH / OUTPUT CHAR / … | Pop n; output the Unicode character at codepoint n mod 1,114,112. |
7 — CONTROL (Control flow)
| Sequence | Mnemonic | Effect |
|---|---|---|
| 70 | CONTROL ENDPROGRAM | End the program immediately. |
| 71 | CONTROL B | Break out of the current loop (invalid outside a loop). |
| 72 | CONTROL IF | Pop cond; if zero, skip to the matching END (or jump to OTHERWISE). |
| 73 | CONTROL END | End the current block (IF / WHILE / DOWHILE / FUNCTION). |
| 74 … | CONTROL CALL name | Call the named function. Name encoded like PUT. |
| 75 | CONTROL WHILE | Pop cond at start of each iteration; loop while nonzero. |
| 76 | CONTROL RETURN | Return from the current function (invalid outside a function). |
| 77 | CONTROL DOWHILE | Run body; pop cond at end; continue while nonzero. |
| 78 … | CONTROL FUNCTION name | Define a function. Name encoded like PUT. |
| 79 | CONTROL OTHERWISE | Separates the if-body from the else-body inside CONTROL IF … CONTROL END. |
Function names are multi-digit numbers, encoded exactly like the argument of PUT.
8 — STACKTOP (Arithmetic & comparisons)
| Sequence | Mnemonic | Effect |
|---|---|---|
| 81 | STACKTOP F | Pop n; push 1 if n = 0, else push 0. (Boolean NOT.) |
| 82 | STACKTOP LT | Pop b then a; push 1 if a < b, else 0. |
| 83 | STACKTOP POW | Pop b then a; push ab (negative b → integer root). |
| 84 | STACKTOP PLUS | Pop b then a; push a + b. |
| 85 | STACKTOP MINUS | Pop b then a; push a − b. |
| 86 | STACKTOP MODULO | Pop b then a; push a mod b (result has sign of b). |
| 87 | STACKTOP PLUSONE | Pop n; push n + 1. |
| 88 | STACKTOP MINUSONE | Pop n; push n − 1. |
| 89 | STACKTOP PRODUCTOF | Pop b then a; push a × b. |
| 80 | STACKTOP QUOTIENTOF | Pop b then a; push a ÷ b (floor division). |
9 — CONTINUED
CONTINUED extends a number from an immediately preceding PUT, CONTROL CALL, or CONTROL FUNCTION command by appending more digits. This allows numbers with more than 10 digits, and functions with very long names.
PUT XXXXXXXXXX:TRI I I TRI I BI I I I TRI CONTINUED XXXX:I BI BI I Pushes 31131211131221
0 — COMMENTARY
Two 10-letter words in a row produce 00, which starts a comment. The comment ends at the next 00.
COMMENTARY INITIALIZE
This text is completely ignored by the interpreter.
COMMENTARY TERMINATED
To embed 00 inside a comment, place any nonzero digits between the opening and closing zeros — the same sequence must appear at both ends:
COMMENTARY here are some words INITIALIZE
This comment won't end at COMMENTARY INITIALIZE.
COMMENTARY here are some words TERMINATED