Ouroboros is an esoteric programming language wherein the code is a bunch of snakes eating their own tails.
An Ouroboros program is a series of lines, each of which represents an independent ouroboros snake. Most commands are single characters (except for string and integer literals). The head is the first character of the line, and the tail is the last character. Each snake starts by not having swallowed any of its tail yet. The
) commands make it swallow or regurgitate sections of its tail, thus changing the flow of execution.
By way of illustration:
Abcdefghij How the code is written (A is head, j is tail) Abcd How the code is treated, in its initial state j e After executing j, the program loops back to A ihgf jiAbc Code after swallowing two characters h d After executing h, the program loops back to A gfe i and j are not executed
Control flow starts at the head and proceeds toward the tail. If it reaches the end of the snake or a section that has been eaten, it loops back to the head. Swallowing and regurgitating characters from the tail is the only control flow method. Regurgitating more than the snake has swallowed causes the tail to come back to its initial position. Swallowing more than the length of the snake causes the entire snake to be swallowed.
Each snake executes instructions in parallel with the others, with snakes from top to bottom each executing one instruction on each tick. If the currently-executing instruction of a snake is swallowed, that snake dies (stops executing instructions). When all snakes are dead, the program halts.
Each snake has a stack, and there is also a shared stack that allows for inter-snake commerce. Empty stacks act as if they contain infinite zeroes (though the true length is accessible using
Many of Ouroboros' commands are taken from ><>, with some tweaks to improve usability.
0-9 Push integer (multiple digits work as a single multi-digit number) a-f Push 10-15 "" Push ASCII values of all characters between quotes, reversed for easy printing
Note that integers and strings can start at the tail of a snake and continue seamlessly across to the head.
\ Swap top two items on stack @ Rotate top three items on stack, bringing third-from-top to top ; Pop stack and discard . Duplicate top of stack $ Toggle whether active stack is the shared stack or own stack (initially own stack) s Set own stack active S Set shared stack active m Pop own stack and push to shared stack M Pop shared stack and push to own stack y Push copy of top of own stack to shared stack Y Push copy of top of shared stack to own stack l Push length of own stack to active stack L Push length of shared stack to active stack
( Pop stack and eat that many instructions of tail ) Pop stack and regurgitate that many instructions of tail w Pop stack and wait that many ticks before resuming execution (useful for synchronization)
+ Pop stack twice and add - Pop stack twice and subtract * Pop stack twice and multiply / Pop stack twice and divide % Pop stack twice and mod _ Negate top of stack I Truncate top of stack to integer = Pop stack twice and push 1 if equal, 0 otherwise < Pop stack twice and push 1 if less than, 0 otherwise > Pop stack twice and push 1 if greater than, 0 otherwise ! Logically negate top of stack ? Push a random floating-point number between 0 and 1
n Pop stack and output as a number o Pop stack and output as a character r Read next nonnegative integer from input and push (-1 on eof) i Read character code from input and push (-1 on eof)
r scans forward until it finds a group of one or more consecutive digits, ignoring any characters that are not
Print digits 0 through 9:
Hello world, straightforward version:
Hello world, shorter version using two snakes:
S"Hello, World!"1( ewSoL!(
Fibonacci sequence (endless):
Collatz orbit of input number:
Test whether input number is prime: