BESPOKE

Prose in Execution


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:

Examples:

Word(s)Digit(s)
I1
tiny4
pythons7
vocabulary0
couldn't7
unintelligible1, 4
I marred a groaning silhouette1, 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:

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:

DigitMnemonic
1I
2BI
3TRI
4FOUR
5FIFTH
6SEXTET
7SEVENTH
8INTEIGHT
9DIGITNINE
0NUMBERZERO

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)

SequenceMnemonicEffect
11 / 13 / 15 / 17 / 19H V / H LDV / … Pop addr from stack; push the value at heap[addr] (0 if unset).
12 / 14 / 16 / 18 / 10H SV / H STRV / … Pop addr then val from stack; store val at heap[addr].

2 — DO (Stack manipulation)

SequenceMnemonicEffect
21DO PPop and discard the top value.
22DO PNPop n; remove the nth value from the top (negative = from bottom).
23DO ROTPop n; rotate the top value down to the nth position.
24DO COPYDuplicate the top value.
25DO COPYNPop n; copy the nth value to the top.
26DO SWITCHSwap the top two values.
27DO SWITCHNPop n; swap the top value with the nth.
28DO TURNOVERReverse the entire stack.
29DO TURNOVERNPop n; reverse the top n values.
20DO ROTINVERSEPop 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.

SequenceMnemonicPushes
315PUT X:FIFTH5
3210PUT XX:I NUMBERZERO10
33123PUT XXX:I BI TRI123
3516180PUT XXXXX:I SEXTET I INTEIGHT NUMBERZERO16180

4 — PUSH (push single-digit number)

The digit after 4 is the number pushed (0–9).

SequenceMnemonicPushes
42PUSH BI2
47PUSH SEVENTH7
40PUSH NUMBERZERO0

5 — INPUT

SequenceMnemonicEffect
51 / 53 / 55 / 57 / 59INPUT N / INPUT INT / … Read a number from input; push it.
52 / 54 / 56 / 58 / 50INPUT CH / INPUT CHAR / … Read one character; push its Unicode codepoint. Push -1 on EOF.

6 — OUTPUT

SequenceMnemonicEffect
61 / 63 / 65 / 67 / 69OUTPUT N / OUTPUT INT / … Pop n; output it as a decimal number.
62 / 64 / 66 / 68 / 60OUTPUT CH / OUTPUT CHAR / … Pop n; output the Unicode character at codepoint n mod 1,114,112.

7 — CONTROL (Control flow)

SequenceMnemonicEffect
70CONTROL ENDPROGRAMEnd the program immediately.
71CONTROL BBreak out of the current loop (invalid outside a loop).
72CONTROL IFPop cond; if zero, skip to the matching END (or jump to OTHERWISE).
73CONTROL ENDEnd the current block (IF / WHILE / DOWHILE / FUNCTION).
74 …CONTROL CALL nameCall the named function. Name encoded like PUT.
75CONTROL WHILEPop cond at start of each iteration; loop while nonzero.
76CONTROL RETURNReturn from the current function (invalid outside a function).
77CONTROL DOWHILERun body; pop cond at end; continue while nonzero.
78 …CONTROL FUNCTION nameDefine a function. Name encoded like PUT.
79CONTROL OTHERWISESeparates 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)

SequenceMnemonicEffect
81STACKTOP FPop n; push 1 if n = 0, else push 0. (Boolean NOT.)
82STACKTOP LTPop b then a; push 1 if a < b, else 0.
83STACKTOP POWPop b then a; push ab (negative b → integer root).
84STACKTOP PLUSPop b then a; push a + b.
85STACKTOP MINUSPop b then a; push ab.
86STACKTOP MODULOPop b then a; push a mod b (result has sign of b).
87STACKTOP PLUSONEPop n; push n + 1.
88STACKTOP MINUSONEPop n; push n − 1.
89STACKTOP PRODUCTOFPop b then a; push a × b.
80STACKTOP QUOTIENTOFPop 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