Fish
- The title of this article is not correct because of technical limitations. The correct title is actually ><>.
- Not to be confused with Fysh.
><> (pronounced as if it were spelled as “fish”) is a stack-based, reflective, two-dimensional esoteric programming language. It draws inspiration from, among others, Befunge. It was invented by User:Harpyon in 2009.
Concepts
><> is a two-dimensional language, meaning the code is not necessarily executed in a linear manner. Using various instructions, the direction the code is read can be changed to either up, down, left or right. It is also a stack-based language, so all operations are performed on a stack. You can also store and retrieve values in the codebox, so making a proper compiler is very hard, if not impossible.
What makes ><> unique is the fact that it supports multiple stacks. A program starts off with one stack, where values are pushed and popped. The program can however create a new stack on top of the original one, with a specific amount of values moved over from the original stack. The program can create as many new stacks as it wants to. When a stack is removed, the values residing on it are moved to the top of the underlying stack. Example here. Each stack is effectively a new scope in the program; this allows for writing functions and snippets to drop into code easily.
Code execution
><> code is laid out in a two-dimensional codebox. The codebox is infinite in all directions, positive and negative. It is traversed by the instruction pointer, or the IP.
- Note: all coordinates for the codebox are given as (character,line), i.e., (column,row).
The instruction pointer starts out at (0,0), i.e. the top-left of the script. It initially moves towards the right, but its direction can be changed using a variety of instructions. When the IP reaches the end of the code in any direction, it will wrap around, or "jump" to the opposite side. The IP will never reach the negative side of the code; this makes this space useful for storing values. Execution will not stop until a ;
instruction is met, or an error occurs.
In the following example, the IP moves upwards, wraps around to the bottom, moves leftwards, wraps around to the right side, goes upwards, then leftwards, and stops.
^ ; < < ^
Mirrors
Mirrors are special kinds of instructions that will change the direction of the IP depending on the direction it already has. For example, if the IP is moving rightwards and meets a \
instruction, it will be "reflected" (unrelated to reflection) downwards. If the IP meets it going downwards, it will be reflected to the right, and so on. Meeting _
horizontally or |
vertically equals a NOP, but meeting them vertically and horizontally, respectively, will invert the direction, and #
will do so unconditionally.
Stacks
><> is stack-based, and thus every instruction except movement-related and the end-execution instruction (;
) do something to the stack. You can push numbers and input, perform modifications and pop output using various instructions. You can also create new stacks, this using the [
instruction. Creating a new stack pulls a specified number of items from the current stack onto the new one. The new stack is completely isolated from the previous one, and an arbitrary amount of stacks can be created on top of each other. When the ]
instruction is met, the current stack is popped and its values are moved back to the underlying stack. If the current stack is the last stack, ]
simply empties the stack and registry.
12345 3[ r ] rnnnnn; ^ ^ ^ ^ ^ | | | | | Output: 12543. The three top values were reversed! | | | | | | | | The second stack is removed, putting its values back to the first stack. | | | | | | The second stack is reversed. | | | | A second stack is created, pulling 3 values from the first stack | | Numbers 1-5 are pushed onto the first stack.
The register
The &
instruction is used to store and retrieve values in a register. If the register is empty, &
stores a value in it. When the register holds a value, &
pushes it back onto the stack.
When creating new stacks, new registers are also created. However, the values aren't moved around; each stack starts off with an empty register, and when the stack is removed, the register is dropped.
Input/output
><> has three input/output instructions: i
for input and o
/n
for output. The i
instruction simply reads a character from stdin. If no more input is available, i
pushes -1
. Note that there is no instruction to input a number, you will have to parse the characters yourself.
While parsing numbers is not very hard, it makes for slow and possibly glitchy programs. Most programs requiring number input reads it from the stack at program start. This is done with an interpreter that supports pre-populating the stack with values. Doing so with the fish.py interpreter looks like this:
$ ./fish.py --code "2*n;" --value 10 20
Output is a bit easier, as you have two instructions: o
and n
. They will pop a value and output it as a character and a number, respectively. The output is naturally written to stdout.
Errors
The following events will cause an error in ><>:
- Division by zero
- Reaching an invalid instruction
- Trying to pop or modify on the stack when it is empty or has too few values
- If the interpreter does not support arbitrary-precision numbers, an overflow results in an error
Although there are multiple reasons an error may occur, there is only one error message: something smells fishy...
Instructions
The following is merely a draft of the instructions in ><>, and is subject to change.
Movement and execution
> < ^ v
|
Change the direction of the instruction pointer (right, left, up, down respectively) |
/ \ | _ #
|
Mirrors; the IP will change direction depending on what direction it already has. |
x
|
Random direction. |
!
|
Trampoline - skip the following instruction. |
?
|
Conditional trampoline - pop one value off the stack. The next instruction is only executed if the popped value is non-zero. |
.
|
Jump - pop y and x off the stack, and move the IP to (x,y) in the codebox. The current direction is retained. Note that you have to jump to the cell before the instructions you want to execute, as the IP will move one position next tick before executing.
|
Literals and operators
0-9 a-f
|
Push the corresponding value in base 16 onto the stack. |
+ - * , %
|
Addition, subtraction, multiplication, division and modulo, respectively. Pop x and y off the stack, and push y operator x . Division is float division (meaning 94,n; outputs 2.25 and not 2 ). Division by 0 raises an error.
|
=
|
Equals. Pop x and y off the stack, and push 1 if y = x , and 0 otherwise.
|
) (
|
Greater than and less than, respectively. Pop x and y off the stack, and push 1 if y operator x , and 0 otherwise.
|
' "
|
Single and double quote - enable string parsing. String parsing pushes every character found to the stack until it finds a closing quote. |
Stack manipulation
:
|
Duplicate the top value on the stack. |
~
|
Remove the top value from the stack. |
$
|
Swap the top two values on the stack |
@
|
Swap the top three values on the stack, shifting them rightwards (e.g. if your stack is 1,2,3,4 , calling @ results in 1,4,2,3 )
|
} {
|
Shift the entire stack to the right and left, respectively. (e.g. when having 1,2,3,4 , calling } results in 4,1,2,3 while { results in 2,3,4,1 )
|
r
|
Reverse the stack. |
l
|
Push the length of the stack onto the stack. |
[
|
Pop x off the stack and create a new stack, moving x values from the old stack onto the new one. See Stacks.
|
]
|
Remove the current stack, moving its values to the top of the underlying stack. |
Input/output
See Input/output.
o n
|
Pop and output as a character and a number, respectively. Output is written to stdout. |
i
|
Read one character from stdin and push it to the stack. The character should not be shown when read from console. When no more input is available, -1 is pushed.
|
Reflection/miscellaneous
&
|
Pop the top value off the stack and put it in the register. Calling & again will take the value in the register and put it back on the stack. See The register.
|
g
|
Pop y and x off the stack, and push the value at x,y in the codebox. Empty cells are equal to 0 .
|
p
|
Pop y , x , and v off the stack, and change the value at x,y to v . E.g. 123p puts 1 at 2,3 in the codebox.
|
;
|
End execution. |
The space character is simply a NOP and is allowed anywhere.
Examples
All the examples are executed using the fish.py interpreter.
Hello, world!
>"Hello World!"0r>o:?v; ^ <
$ ./fish.py helloworld.fish hello, world
With a lowercase "W" and with a comma by User:MihaiEso
>"Hello, world!"0r>o:?v; ^ <
Smallest Version by User:BrainFuckGirl
"!dlroW ,olleH"l?!;oe0.
Cat Program
A cat program by User:Ractangle and User:BrainFuckGirl, requiring pre-populating the stack with values:
0rv o< >:?^;
Alternative version by User:Ractangle, reading from stdin:
>i:1+?v; ^ o<
A tiny cat program reading from stdin. Made by User:BrainFuckGirl
i:0(?;o
FizzBuzz
0voa ~/?=0:\ voa oooo'Buzz'~< / >1+:aa*1+=?;::5%:{3%:@*?\?/'zziF'oooo/ ^oa n:~~/
$ ./fish.py fizzbuzz.fish 1 2 Fizz ... 98 Fizz Buzz
Fibonacci sequence
Outputs Fibonacci numbers until stopped. The execution is slowed down using -t 0.01
, to avoid being spammed to death with the endless Fibonacci sequence.
10::n' 'o&+&$10.
$ ./fish.py fibonacci.fish -t 0.01 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 ...
Lucas sequence
Outputs the Lucas numbers until stopped.
2n' 'ol?/21>::! $&+&\ /
$ ./fish.py lucas.fish -t 0.01 2 1 3 4 7 11 18 29 47 76 123 199 322 521 843 1364 2207 3571 5778 ...
Factorial
Calculates the factorial of the input number. Assumes the input is a non-negative integer. Notice that the input value, 10
, is supplied using the -v switch of the interpreter.
:?\~11>*l1\ -1:/ ;n\?- /
$ ./fish.py factorial.fish -v 10 3628800
Quine
Outputs its own source code.
"r00gol?!;40.
$ ./fish.py quine.fish "r00gol?!;40.
Another one, this one is multi-line
0>:a$f8+$p1+:5-?vv ^ <>~0v v < < >0v ;^?-6:+1~< v < < >$:{:}$go$ 1+:f9+-?^^
Square root
A function (isolated stack; remove the 1[
and ]
instructions to create "inline" version) that calculates and outputs the square root of the top of the stack/input number.
1[:>:r:@@:@,\; ]~$\!?={:,2+/n
$ ./fish.py sqrt.fish -v 64 8
Brainfuck interpreter
Program and input seperated by !
.
v 1 0 >$ >$ \ >:@$:@i:0(?^$:2=?^$:3b*-0=?\v/ >:&$:1=?v>$@p&0(?v$1+ \ 02]p00~~<> :'+'=?^\ $$ >1-0p \01-\ /^?='>': < d+ v <} v?= \ > :'<'=?^\ %e v}]p$p4r}:r:$4[2@:/f1+/ /^?='-': < \/ >{1+:00g=?\:1g:e-?^~:}0a. > :'['=?^\ / -1-:/ /^?=']': < >1+:00g=?;:1g0$. > :'.'=?^\ ^ ~< $\.51$~~ ~^?=',': < '['~ 20g:3g ?^>$4g^ ']'~ 20g:3g0=?^^ ^ < \ '+'~ 20g:3g1+3$@p^ ','~ 30g:1+30p2g 20g3p/ '-'~ 20g:3g1-3$@p^ '.'~ 20g3go / '<'~ 20g1-20p\ ^ < '>'~ 20g1+20p/
echo '++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.' | ./fish.py brainfuck.fish Hello World!
echo '-,+[-[>>++++[>++++++++<-]<+<-[>+>+>-[>>>]<[[>+<-]>>+>]<<<<<-]]>>>[-]+>--[-[<->+++[-]]]<[++++++++++++<[>-[>+>>]>[+[<+>-]>+>>]<<<<<-]>>[<+>-]>[-[-<<[-]>>]<<[<<->>-]>>]<<[<<+>>-]]<[-]<.[-]<-,+]!Esolangs' | ./fish.py brainfuck.fish Rfbynatf
Interpreters
fish.py
The "official" interpreter, or the one written by the author. The latest version is available here. Requires python versions 2.7 or 3.2 or later. For usage information, run it with the --help switch.
fishlanguage
An online interpreter, written in TypeScript. Features animation of the instruction pointer moving through the program, configurable execution speed, and display of stack contents. (Formerly found at fishlanguage.com.)
Mousetail's Fish Interpreter
Another online interpreter in Typescript. Able to create sharable links, pause execution, and see the state of multiple stacks at the same time. Inputs do not reset when repeatedly testing a program.
go-fish
An interpreter written by redstarcoder. It follows the same behaviour as the fish.py interpreter, but can also follow the fishlanguage.com behaviour with "-m" set. Download at GitHub.
fish.java
An interpreter written by User:Cxarli. It has the same console arguments as the "official" interpreter. Get the source from GitHub here. (dead link)
fishr
An interpreter written in Rust, by Marc Noirot. It has roughly the same console arguments as the "official" interpreter. Get the source from GitHub here.
fish-jit
A just-in-time compiling interpreter, written in RPython. Stack values are stored as arbitrary precision fractions, and converted to float only when displaying. Get the source from GitHub here.
Older interpreters
The following interpreters were written towards an older version of ><> that featured multithreading. The multithreading capabilities were removed and replaced with multiple stacks support, which was deemed more useful (not that esoteric languages are useful in the first place). These interpreters may not work with some updated instructions, like p
, [
and ]
. You can of course still use these interpreters using the old documentation.
Python
The old version of the official python interpreter is available through Gist. (dead link)
Invoke it by first making sure you have installed python, and typing python fish.py <script> [tick]
into your system's command line. Script is replaced with a .fish file, and tick is optional and defines a delay in seconds between each instruction, to slow down execution for debugging etc. It should work with both python 2.x and 3.x, as well as both Windows, Linux and Mac.
Delphi
Another interpreter, written in Delphi, is a result of a so-called 'code-golf challenge'. It interprets every instruction (except the threading related instructions) in about 1290 characters of source code. (A version with threading support is also available on the same site.) Get it here!
Compile the code into a console application with any Unicode-enabled version of Delphi (a port to the FreePascalCompiler FPC is trivial). Invoke the resulting executable and supply the path to a .fish file on the command line. Speed can be limited by increasing the Sleep() time in the code.
More
There are several interpreters in a multitude of languages available in the StackExchange code-golf challenge.