We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.
pH
pH (also known as BYOS) is an esoteric programming language created by User:Thlot in 2026. Its code is made up of two parts: a function defining section and a numbered list of actual code to run. Notably, it was not created to be hard to use, and has many intentionally convenient functions! It also has time travel.
Data Storage
pH operates on a 2-dimensional grid of cells all starting at 0; there are no fundamental limits on either the values in the cells or the amount, but an interpreter would obviously have to constrain both. While these cells are primarily used for numbers, they can also store text. Attempting to increment a non-number will set the cell to 0.
Syntax: Functions
The first part of a pH program is made up of function definitions, using the structure of function name[code]. The code inside functions can only be used in these functions: the actual code, which we will get to later, uses none of these base level instructions. They go as follows:
| Command | Function |
|---|---|
u |
Move up by one cell |
d |
Move down by one cell |
l |
Move left by one cell |
r |
Move right by one cell |
+ |
Increments current cell by 1 |
- |
Decrements current cell by 1 |
s[x, y] |
Accepts two inputs and goes to that position |
a[input] |
Sets the value of the current cell to input |
i |
Takes input. Can be used in the place of an argument for any command with []s. When using a function with i's in it, an argument must be specified for each one |
j[line] |
Jumps to specified line |
r |
Reverses the order that the code is read (time travel) |
o |
Outputs current cell's value |
![value] |
Halts the current function and moves on to the next unless value matches that of the current cell's |
> |
Halts the current function unless time is currently flowing forwards |
< |
The same, but for backwards |
X |
Terminates the program. Any program without one somewhere is considered invalid and will not run. This does not forbid loops |
Functions are specified in layers separated by newlines. Layer two and onwards can now use the following function:
{}
Within these brackets, code using functions defined in previous layers can be turned into functions themselves.
The Actual Code (That Gets Run)
Once all functions have been defined, use $$ to end this stage. From here on out, you can only use your previously defined functions. This is pretty simply done as function[code]. Each line must be given an identifier: usually you just use numbers in order, but anything can be used. The structure is:
identifier $ code
During this functions with arguments must be given them as function[input]. The following characters can be used in place of an actual input:
| Command | Value given |
|---|---|
% |
Takes external input |
# |
Takes the value of the current cell |
Examples
Hello World
hello[s[0, 0]a["hello world"] die[X] $$ 1 $ hello[] 2 $ die[]
Truth-Machine
ask[s[0, 0]a[i]] finish[![0]j[3]] backward[>r] oloop[o![1]>r] die[X] $$ 1 $ ask[%] 2 $ finish[] oloop[] 3 $ oloop[] die[]
Cat
cat[a[i]or] rev[<r] die[X] jdie[![0]j[2]] setup[s[0, 0]+] $$ 1 $ setup[] rev[] jdie[] cat[%] 2 $ die[X] rev[]
Simplest Valid Program
a[X] $$ 1 $ a[]