Each line of an Ouroboros program represents a snake eating its own tail, with the beginning of the line being the head and the end being the tail. The only control flow operations are commands to eat or regurgitate characters of the tail. When the instruction pointer reaches the last part of the line that hasn't been eaten, it loops back to the beginning. To stop execution, simply swallow the instruction pointer.
Ouroboros has a Stack Snippet interpreter.
Outputs the top of the stack as a number. An empty stack is treated as if it contained infinite zeros, so this outputs
0. No characters are ever eaten, so the program loops (and prints) infinitely.
1 and then uses
( to eat that many characters from the end of the snake. This means eating the last character. However, since that's where the instruction pointer currently is, the snake dies and the program terminates.
The program would also terminate if the number were
2, or indeed any larger number; in that case the entire snake would be swallowed. (Physically impossible, but hey--this is a metaphor.)
Although Ouroboros processes one character per tick, it still supports multi-digit numbers in the expected way. This program will push and output
32 infinitely (rather than, for instance, pushing
2, and outputting only the
One interesting side effect: a multi-digit number is recognized as such even when it bridges the end of the snake. The code
2n3 will first output
2, but thereafter will output
r reads a positive integer from input, grabbing all contiguous digits until it finds a non-digit.
n outputs as a number.
o outputs this as a character (newline). Thus, an input of
1 2.3 -4abc55 will yield
However, because this snippet doesn't terminate the loop when the input is used up, the program will continue:
r will start giving
-1s to signal end-of-input, and
n will keep outputting them indefinitely.
Prints one or more
0s, with the exact count depending on random numbers.
n behaves as in snippet 1, outputting a
0 from the empty stack.
?2* generates a random floating-point number between 0 and 1 and doubles it. Then
( eats that many characters (rounded down). Thus, if
? generated a number >= 0.5, the program halts; if not, it loops, prints another
" toggles between executing characters and treating them as a string. As in other 2D languages, you can define a string using only one quote mark because the instruction pointer wraps around. A key difference with Ouroboros, however, is that the string is pushed in reverse order, so that the first character is on the top of the stack. This means we don't need to write strings backwards or have a stack-reverse operator like ><> does.
The above code pushes
"oooo(" and outputs the first four characters (the
os). It then uses the last number remaining on the stack (
40, the charcode of
() as the argument to the
( command. Eating 40 characters definitely swallows the IP, and the program halts.
Truth machine program.
r reads a number from input, or -1 for EOF.
.* multiplies it by itself, keeping 0 and 1 the same but mapping -1 to 1.
.n dups and outputs the number. Finally,
!( logically negates and eats that many characters of the end of the snake. If the number was
0, this eats the
( and dies. If the number was
1, this eats zero characters, and execution loops back to the beginning of the snake, printing
i reads a single character from input, pushing its charcode (or -1 on EOF).
.0< duplicates and tests if the value was less than 0; i.e., pushes 1 on EOF and 0 otherwise.
2*( multiplies by 2 and swallows that many characters. On EOF, this eats
(o and ends the program; otherwise, nothing is eaten, and
o outputs the character from input. The snake then loops back to the beginning.
In writing this snippet, I realized that cat can actually be done in four characters:
i.)o. Go read the explanation on that answer for some crazy abuse of undefined behavior.
(Length 9 snippet pending)
Outputs the Fibonacci sequence, starting from 0 and continuing indefinitely.
First, we need to initialize the stack by pushing a
1. The trouble is that any initialization code at the head of a snake will run every time through (since it's at the head, we have no way of eating it). Therefore
.!+ is designed to turn the top of the stack into a
1 iff it was previously
0 (which is the case when the stack is empty).
.! dups and logically negates (
1 if the value was
+ adds that result to the top value.
(For a version that uses a second snake to perform the initialization, see the GitHub readme.)
Now the bulk of the program. Call the two numbers on the stack
x is smaller and
y is on the top of the stack.
x to the top, and outputs a copy of it.
ao outputs a newline (as in snippet 4), and
x to a copy of
y. Now the stack contains
x+y, and we proceed to the next iteration.