From Esolang
Jump to navigation Jump to search

Onione is an esolang by User:BoundedBeans based on Stable Diffusion images of piles of onions.


Everything in Onione is an expression. Every expression type has a series of uppercase letters and colons followed by a pair of square brackets with an ampersand-separated list of expressions inside. An expression marked with a caret followed by a series of lowercase letters followed by a caret followed by a standard expression is a deferred expression, used in conditionals and loops. If there are no lowercase letters then the expression is just deferred and not assigned to a name. Another syntax for deferred expressions is a series of lowercase letters enclosed in single quotes, this copies a caret-marked expression by name, so you don't have to repeat a ton of stuff. Unless specified that an expression MUST be deferred, an expression usually MUST NOT be deferred.

Data types

The only two data types are numbers and rgb 512x512 images.

Expression types

Anywhere where it says that a value is appended to the parameter list, the same number of entries are removed from the end once the inner code finishes. Anywhere where it says that the parameter list is replaced, the previous contents are saved and restored once the code ends.

Expressions always evaluate the non-deferred arguments first, from left to right, then run the deferred arguments with the special semantics provided by the specific expression type. Finally, the expression returns the value.

Command Meaning
GENERATE[seed1&seed2&seed3&seed4] Use Stable Diffusion 2.1 to generate an image with the prompt a large pile of onions and the seed calculated by ((seed1 << 24) | (seed2 << 16) | (seed3 << 8) | seed4) & 0xffffffff. Return the image.
ZERO[] Return the number 0.


Return the value of the specified channel in the provided image at the zero-based pixel coordinates.
PIXEL:SET[image&x&y&red&green&blue] Return a new image with the pixel set there. The red, green, and blue values use the least significant 8 bits only, while the x and y values use the least significant 9 bits only.
XOR:FIVE:TWELVE[num] Returns num with the bit with value 256 flipped.
SHIFT:LEFT[num&bit] If num is 0 or 256, returns 0. If num is anything else, returns (num << 1) | (bit & 0x1)
FIVE:TWELVE[one&two&three] If passed 1, 2, 3, returns 512. If passed 4, 5, 6, returns 513. Otherwise, returns 0. This is to allow the numbers 512 and 513 to be made since SHIFT:LEFT is unable to make them.


Accesses the parameter with the given index and type. These are in a per-type list which is appended to inside of certain expressions.


Sets the param in the expression.


Appends the parameter to the parameter list of the given type, runs condition (condition must always return a number). If condition returns 0, run if-false with the parameter still given, otherwise, run if-true with the parameter still given. Having the condition be ZERO[] is the easiest way to get state, since it will always run if-false and will provide the parameter. The return value of if-true or if-false (whichever runs) is the return value of this expression. condition, if-true, and if-false must be deferred.
COND:SWITCH[num-param&if-bit-on&if-bit-off] Checks num-param's least significant bit, if it is 1, run if-bit-on, if it is 0, run if-bit-off. Either way, the branch that runs will have the number parameter list appended with num-param shifted right by one bit. The return value of if-bit-on or if-bit-off (whichever runs) is the return value of this expression. if-bit-on and if-bit-off must be deferred. Shift right can be accomplished with COND:SWITCH[num&^^PARAM:GET:NUM[new-index]&^^PARAM:GET:NUM[new-index]] where num is the value to shift right and new-index is the lowest unoccupied number parameter list slot.


Runs code with the parameter appended to the parameter list of the given type, repeatedly until code returns 0. code must always return a number. ending-code is then called with num-param appended to the parameter list (which code may have changed), and its return value (which should be the same type as num-param and the one specified in the name of the expression) will be the return value of this expression. code and ending-code must be deferred.

In order to send a lot of data in and out of the loop (since they must be the same type), either use LOOP:IMAGE or set an image parameter made outside the loop while in it.

PRINT:NUM[num] Prints the least significant 8 bits of num as a byte.
PRINT:IMAGE[image] Displays the image on screen.


Runs code with an input number or image appended to the parameter list of the given type.
STACK[image&direction] Images have an internal stack of images below them. This command uses that stack. If direction is 0, return a new image that is the same as the given image but with the images' current value duplicated and pushed onto its stack. If direction is anything else, returns a new image where the value is replaced with the value on the top of the stack and the top of the stack popped.


Loads a list of characters from the number parameter table, uses it to load a library from an Onione program, or a named function from a Unix shared library (.so), or a .dll file. This returns a special value that can be used in LIBRARY:CALL
LIBRARY:CALL[library-func] Call the library function with the two parameter lists as arguments.
SHELL[start&length&code] Loads a list of characters from the number parameter table, forms a shell command, runs it. Appends the output byte by byte into the number parameter list, runs code. code must be deferred.
IMAGE:TO:PARAM[image&x&y&width&height&stack-depth&code] Runs code with the pixels in the image in the rectangle replacing the number parameter list (not append!). If stack-depth is not zero, it also moves down the stack that many levels to get more pixels. code must be deferred.

How to program

It's insanely tedious to program in this language. The only way to get numbers other than 0 and 256 (256 is accessible with XOR:FIVE:TWELVE[ZERO[]]) are to find them inside the pixels of Stable Diffusion 2.1 onion pile images generated with the 8 available starting seeds that use only 0 and 256 as elements, at the four available pixels with those numbers as coordinates. However, if a specific number is not accessible from those seed/pixel combinations, you can use the numbers that are to make new seeds until you have all 255 base numbers which get you to 511 with the XOR:FIVE:TWELVE command, 512 and 513 with the FIVE:TWELVE command, and further with the SHIFT:LEFT command. From there math is really tricky, you'll need to use an image as an increment/decrement table and build everything else from there. Or, if someone makes a math library, you can always just use that (cheater!).