International Phonetic Esoteric Language

From Esolang
Jump to navigation Jump to search

The International Phonetic Esoteric Language, abbreviated to IPEL, is a stack-based esoteric programming language by User:Bigyihsuan based on the idea of using the Wikipedia:International Phonetic Alphabet (IPA) as the primary instruction set. Its interpreter can be found here


IPEL uses 2 stacks to store values, named the unvoiced and voiced stacks, as well as a general-use register. There is a pointer to the current stack that gets switched with a set of instructions, further detailed below.

An additional execution stack is used by the interpreter for loops and control flow.

IPEL has three types: numbers, strings, and lists. Numbers represent both integers and floats and act as such. Strings are chains of characters stored as a single value. Lists are a container type that can contain any combination of the three types.

IPEL has a large instruction set that consists solely of single-character strings taken from the IPA.

IPEL also has a labeling system that allows for arbitrary jump points. There is a function system as well that supports recursion.

The Three Stacks

The three stacks consist of 2 data stacks and 1 execution stack. The data stacks, named "Unvoiced" and "Voiced", are directly worked on by most instructions. The current data stack, as well as which one it is currently, can be changed by some instructions as detailed below.

The execution stack has only the top element exposed by certain instructions. It is used for both storing loop index counters, as well as points for execution to return to when using loops and functions.

The Register

A general-use register is available. It holds a single value that is set by an instruction, gotten by a different instruction.

It is colloquially called the wegister.

Character Stack Effect Mnemonic Description
w (ele -- ) SETREG Pops a value off the stack and sets the register to it.
ʍ ( -- ele) GETREG Pushes a copy of the register onto the stack.


The three types when encountered by the interpreter are pushed onto the currently selected stack.

Code Type Explanation
0-9 Number Single digit.
{...} Number Number with more than 1 digit, or a float.
"..." String String
[...] List List elements separated by periods .


Numbers represent both integers and floats. Numbers are defined in one of two ways: digit form and multidigit form. The digit form is any digit in 0-9A-Za-z. The multidigit form consists of a whole number, then an optional decimal point with fractional part. They are surrounded by curly braces {}. Floats and negative numbers can only be declared using the multidigit form.


7 ( -- 7)
78 ( -- 7 8)
{123} ( -- 123)
{1.23} ( -- 1.23)
1{3.3}0 ( -- 1 3.3 0)
{3.5} ( -- 3.5)
{abc} ( -- 13368)


Strings are a sequence of characters. They are delimited by double quotes "..." Strings can be considered a "pseudo-list" of integers, with each integer representing the ASCII/Unicode value. This lets it be treated like a list with list-manipulating instructions.

Escape sequences are allowed for strings; they can be one of the following subset of the Python escape sequences:

Escape Sequence Meaning
\newline Backslash and newline ignored
\\ Backslash (\)
\' Single quote (')
\" Double quote (")
\a ASCII Bell (BEL)
\b ASCII Backspace (BS)
\f ASCII Formfeed (FF)
\n ASCII Linefeed (LF)
\r ASCII Carriage Return (CR)
\t ASCII Horizontal Tab (TAB)
\v ASCII Vertical Tab (VT)


"abc" ( -- "abc")
"a""b""c" ( -- "a" "b" "c")
"" ( -- "" )
"a \
b" ( -- "a b")
"\n" ( -- "\n")
"\"<>" ( -- "\"<>")
"'hello'" (-- "'hello'")


Lists are a type that stores other types, specifically any combination of numbers, strings, or lists. They are delimited by square brackets [].

List elements are separated by periods .. Lists can be nested inside each other by creating a list inside a list.


[] (empty list)
[["nested"].["list".["in list"]]."it is"]

Type Truthiness

IPEL primarily implements the concept of booleans by using numbers: non-zero is truthy, and zero is falsy. In the same vein, strings and lists are also truthy and falsy; empty strings and lists are falsy.


Comments are modelled after Forth: text surrounded by parentheses (...) are comments. Just like Forth comments, you can't next comments; (com(com)ment) would terminate the comment at the first ).


(this is a comment)
(This is a comment (not nested)
(comment with
    (a newline and tab)

Labels, Jump, and Skip

Labels are characters representing the label name surrounded by pipes |...|. These are used in conjunction with the goto instruction ɔ. When a label is placed after ʟ, execution will jump to the label, then continue execution.

The skip instruction ʌ pops the stack, checks for truthiness, and skips the next instruction if it is truthy. This allows for conditional jumps by placing instructions to check a condition before the skip, and jumping if the condition is falsey.

Code Stack Effect Description
|label| ( -- ) Defines a label.
ɔ|label| ( -- ) Jump to the specified label.
ʌ (con -- ) Pop the stack. If con is truthy, skip the next instruction.


Functions are possible in IPEL by doing the following:

<name>/code\ (function definition)
<name>       (function call)

Function bodies can contain any code at all: values, instructions, function calls, labels, anything. The ending symbol for a function boundary \ for the interpreter does nothing when execution did not come from a function. Expect undefined behavior or errors if you jump into a function body from a different function, such as <f>/abc|l|def\ <g>/ʟ|l|\.

Recursion is possible by calling the function from within itself: <f>/code <f> code\. It is up to you to set base cases.


For loops are similar to Forth DO-LOOPs. The general structure is as follows:

(value: end start -- ) (exec: -- end start)

When ɑ is encountered, 2 numbers are popped from the current value stack and pushed onto the execution stack. When ɒ is encountered, it checks the execution stack. If index < end, jump to the associated ɑ.

index is manipulated by the 2 instructions e and ø. e pushes a copy of index onto the current value stack. ø pops a value from the current value stack and sets index to that value. This is the same with the limit with æ and œ, respectively.

Note that, unlike Forth, ɒ does nothing with index other than compare it against end.

There is also the ɛ instruction, which clears the execution stack of index and end, and exits the loop.

Character Stack Effect Mnemonic Description
ɑ (end start -- ) FOR Pops 2 values for index bounds. Loop jumps back to here if index < end.
ɒ ( -- ) LOOP If index < limit, jump to associated For. Else, continue.
e ( -- index) GETIDX Pushes the current loop's index. NOP if not in a loop.
ø (index -- ) SETIDX Sets the current loop's index to index.
æ ( -- limit) GETLIM Pushes the current loop's limit. NOP if not in a loop.
œ (limit -- ) SETLIM Sets the current loop's limit to limit.
ɛ ( -- ) EXIT Discards the current loop's data from the loop stack, and exits the loop. NOP if not in a loop.


As of interpreter version v1.4.0, GETIDX, SETIDX, GETLIM, and SETLIM access the execution stack directly and run if and only if there is a valid value for it to get or set. The *IDX instructions use the top value, while the *LIM use the 2nd to top.

Because both loops and function calls use the same execution, it's possible to change where a running function will return to using *IDX and *LIM.

<f>/"Yes"o e2sø\
<f> "No"o "Skipped no"o
(Will print "Yes" then "Skipped no". Note that "No"o counts as 2 instructions.)


Bilabials: Voicings

Bilabial consonants handle the selection of the current stack.

Character Stack Effect Mnemonic Comment
ɸ - UNVOICED Sets the voicing to Unvoiced.
β - VOICED Sets the voicing to Voiced.
ɓ ( -- voicing) VOICING Pushes the current voicing. 0 for unvoiced, 1 for voiced.

Plosives: Stack Operations

Plosives modify the stack.

Character Stack Effect Mnemnomic Comment
p (a -- ) POP Pop and discard the top element of the stack.
b (a -- a a) DUP Duplicate the top element of the stack.
t ( -- size) SIZE Push the size of the stack.
d (a b -- b a) SWAP Swap the first and second elements of the stack.
ʈ (c b a -- a c b) RCW Rotate the top 3 elements clockwise (upwards).
ɖ (c b a -- b a c) RCC Rotate the top 3 elements counterclockwise (downwards).
c (d b a c -- d c b a) SORT Sort the stack. Numbers before Strings before Lists. Order of lists in the stack is preserved. Lower values on top.
ɟ (a b c d -- d c b a) REV Reverses the stack.
k A(a -- ) B( -- a) GIVE Pop the top of the current stack and push it onto the other one.
g A( -- a) B(a -- ) TAKE Pop the top of the other stack and push it onto the current one.
q (a b -- a b a) OVER Push the 2nd element from the top of the stack.

Central Vowels: Comparisons and Logical Operators

Approximates and laterals represent comparisons. For all instructions, 1 is pushed if true, and 0 if false.

ASCII/Unicode order is used for strings. Empty strings are first, followed by shorter stings.

Comparing lists does not work except for the ə "Equal to" operator, where it will check for equality. The interpreter will NOP the instruction if it isn't the case

Character Stack Effect Mnemnomic Comment
ɨ (a b -- a>b) GT Greater than
ʉ (a b -- a>=b) GE Greater than or equal to
ə (a b -- a==b) EQ Equal to
ɘ (a b -- a<b) LT Less than
ɵ (a b -- a<=b) LE Less than or equal to
ɜ (a b -- a and b) LAND Logical AND
ɞ (a b -- a or b) LOR Logical OR
ɐ (a -- not a) LNOT Logical NOT

Frontal Fricatives, Taps/Flaps, Trills: Mathematics

Fricatives, taps, flaps, and trills represent mathematical instructions.

These only apply to numbers. Otherwise, the interpreter will NOP the instruction.

Character Stack Effect Mnemnomic Comment
s (a b -- a+b) ADD Addition
z (a b -- a-b) SUB Subtraction
f (a b -- a*b) MULT Multiplication
v (a b -- a/b) DIV Division; will return 0 if b == 0. Always returns a float.
(a b -- a%b) MOD Modulo (Labiodental Tap ⱱ)
ʃ (a b -- a**b) EXP Exponent; Base a, exponent b
ʒ (a b -- log(a, b)) LOG Logarithm; Base a, exponent b
θ (a b -- a>>b) RSH Bit shift a to the right b bits
ð (a b -- a<<b) LSH Bit shift a to the left b bits
ʂ (a b -- a&b) BAND Bitwise AND
ʐ (a b -- a|b) BOR Bitwise OR
r (a -- !a) BNOT Bitwise NOT
ɾ (a -- -a) INV Inverts the sign of a.
ɽ (a -- ceil(a)) CEIL Rounds a to the largest integer
ʙ (a -- floor(a)) FLOOR Rounds a to the smallest integer
ɬ (a b -- max) MIN Minimum
ɮ (a b -- min) MAX Maximum

Back Fricatives, Taps/Flaps, Trills: List and String operations

Back fricatives, taps, flaps, and trills represent operations on lists. String operations are also in this section.

Character Stack Effect Mnemnomic Comment
x (abc def -- abcdef) CAT Concatenation. Implicitly casts its arguments into strings, then lists if they are not lists.
ɣ (a ... z n -- list) NCAT Concatenates the next n elements popped off the stack into a list of length n. Will NOP if n is not a number and does ceil(n) if it is.
ħ (a -- a n) LEN List length. Pushes the length of the element peeked. Casts a to a list to get its length. a's type is retained.
ʀ (list -- a b ...) LSPLIT Splits a list into its individual elements. Implicitly casts list to a list.
h (list n -- list e) GET Returns the element e at n, 0-indexed. Will NOP if n is not a number and does ceil(n) if it is
χ (num -- str) CHR Converts a number to a single-character string, based on its ASCII/Unicode value. Will NOP if num is not a number, and ceil(num) if it is.
ʁ (str -- n1 n2 n3) SSPLIT Converts a string to a list of integers representing their ord() values. Will NOP if str is not a list of single-character strings or a string.
ʕ (list -- str) LTOSTR Converts a list to a string.


Input and output is handled by the frontal closed vowels and the back central vowels.

Character Stack Effect Mnemnomic Comment
i ( -- str) LINE Pushes a line from STDIN as a single string.
y ( -- str str str) WORD Pushes a line from STDIN as multiple strings, separated by whitespace.
ɪ ( -- ele) DATA Pushes an IPEL value onto the stack. Can push numbers, strings, and lists. Defaults to pushing strings if no valid numbers or lists are found.
o (ele -- ) PRINT Pops and outputs to STDIN with trailing newline.
ɤ (ele -- ) LPRINT Pops and outputs to STDIN. Will cast lists to strings.
u (ele -- ) CPRINT Pops and outputs to STDIN, with no trailing characters.
ɯ (ele trail -- ) TPRINT Pops and outputs ele to STDIN with a trailing string trail.


Hello, World!

"Hello, World!"o




The function expects a number n on the stack and leaves n!.



The function expects a number n on the stack and leaves the n-th Fibonacci number. Recursive implementation.


External Resources