pith is a 3-stack esolang themed around vectors, designed by User:ZippyMagician.
pith is a language based around vectors. It features 3 stacks; The left stack I, the right stack J, and the control stack N. Each command is one byte, with two data types also present in the source code. In general, a pith program will look like a sequence of ascii characters, with occasional newlines. All characters not used by pith are ignored, which makes comments using text possible without any delimiter.
Each program written in pith is split into a line-by-line structure, wherein the
, operator can jump to various other lines. pith is not space sensitive, but is newline sensitive. If a program reaches the end of a line but hasn't halted, it will move onto the next line. If there is no next line, the program will terminate. Similarly, jumping to a line past the last one will terminate the program.
The two data types found in pith are vectors and floats. Floats are just a 64-bit floating point number as defined by the IEEE 754 standard. A vector is an array of two of these floating point numbers, stylized as
Since there are a sizable amount of operators, they are separated into different sections. X represents the argument. If an operation takes an argument, it comes after the operator.
||N||Construct vector such that the top values of I and J are pushed to N as <I, J>||N/A|
||N||Deconstruct vector such that vector <A, B> sees A being pushed to I and B to J||N/A|
||N||Pop a value from I and push to J||N/A|
||N||Pop a value from J and push to I||N/A|
||Y||Duplicate the top vector of N X times.||default value of X is 1|
||N||Pop top value from I||N/A|
||N||Pop top value from J||N/A|
||Y||Construct vector <A, B> based on argument [A, B] and push to N, or construct vector [M, 0] based on argument M||N/A|
||N||Calculate the dot product of the top two items in N and push to I and J||N/A|
||N||Add the top two items in N||N/A|
||N||Subtract the top two items in N||Given the top of N: [<A, B>, <C, D>], replace with: [<A-C, B-D>]|
General math operations
||N||Calculate the sign of the magnitude of the top item in N and push to I and J||N/A|
||N||Deconstruct the top item in N, take the absolute value of both sides, and push to I and J, respectively||not affected by |
|N||Calculate the magnitude of the top item in N and push to stdout as char||N/A|
||N||Calculate the magnitude of the top item in N and push to stdout||N/A|
||Y||Pop X vector magnitudes from stdin and reconstruct, pushing to N.||default value of X is 1|
||Y||Pop the top vector of N. If its magnitude is 0, jump to line X||N/A|
||N||Halts the program||N/A|
||N||Jump to the matching
||N||Any operation that pushes the same value to I and J will instead push to one of the following, which cycles on each instance of this op: [I, J, both]||N/A|
Only works when the output is a whole number
- Initialize the program with a line dedicated to
:0*, which will push a 0 to both the I and J stacks. Repeat this for the number of registers the program will make use of. Follow it with a
line# of first instructionto avoid running any dedicated lines for jumping.
- For each command
X -1, add a line which will use
=to navigate to desired value to modify,
:1+to increment, and then
*to move all reconstructed vectors back into the stack
- For each command
X Y, add a line which use
=to navigate to desired register in stack,
DEDICATED LINE #, followed by
:1-and then repeated
*to move all vectors back to the stack, and then
line# + 1
Dedicated lines exist so the stack can still be replaced when this jump occurs. To do this, simply make the line contain
* repeated to remove all registers still on the stack, and then
:0, followed by
Y + 1 + OFFSET where
OFFSET is the number of dedicated lines used by jumps.
If compiled by hand, you could use the same dedicated line for multiple jumps if they go to the same place.
While bulky and impractical, this is a simple way of proving Turing-completeness, instead of just hand-waving it due to laziness.
1 -1 1 1 1 1
:0*:0,2 Initialize registers (only one used) *:0,3 Dedicated line, second and third instructions can share this =:1+* First instruction =&2%=+,1:1-*:0,4 Second instruction =&2%=+,1:1-*:0,5 Third instruction