Page loaded at 02/06/2023 18:56:40 «Reactions can be referenced by surrounding expressions with colons as in :sus:»

Random Content


05/02/2023 05/02/2023 11:29:10#238
static/parallel fizzbuzz viridis.png

[Viridis Esolang]

Viridis (from Latin Bufotes viridis, "Green toad") is an interpreted statically-typed esoteric programming language in which all variables are shared between all created processes by default. The language features 6 basic data types similar to those of C and arrays containing those datatypes, which can be multidimensional.


Inspired by Python multiprocessing.Array class, which is an array of ctypes that can be accessed by multiprocessing.Process processes quickly and without the limitations of a Manager-based object. Eremias, another esolang of rpyth, uses a Manager-controlled dict for all the variables, which is easy to work with, but comes with the cost of it being painfully slow and normally mutable classes being immutable within the dict.

Viridis uses an array of unsigned chars instead, which can be altered on demand, yet requires interpretation during the time of access. Interaction with arrays can be optimized as there is no need to load the whole array to modify a value within it. The only downside to the usage of arrays so far is that it is of constant length throughout whole execution of the program, normally 2^16 unsigned chars, but can be made bigger if needed.


Looks quite like an assembler, accepts kebab-case for variable names. So far there are three main operation types: variable creation, modification and usage of functions. Variables are initialized within the array while the program is running. You can either omit array shape or value, never both. Value, when omitted, is filled with zeroes of specified type according to the space in case it's an array. Modification is always written as:

>target operation= values

Operations can be +, -, *, ^, etc. The values are separated by delimiter, [but act differently if there is only two of them]. Let me show you how.


>target -= value1, value2


>target = value1 - value2

05/02/2023 05/02/2023 11:50:25#239



>target -= one, two, three


>for n in [one,two,three]:

> target-=n

This may not seem obvious, but was made for convenience. Functions always start with the name of the function, and then the arguments. "Do" functions are special, as the first argument in them is always the name of a user-defined function. Speaking of which, execution starts from main. Doif also offers usage of conditions, which are separated by spaces and are joined with "and" operator by default. Due to the lack of Boolean values as a data type, 0 in any data type is treated as False and everything else as True. Conditions can be created via the <=, ==, >= operators. Dowhile is doif, but repeated and dofor even allows you to cycle through an array, which are normally written as [1,2,3,4,5], but this exact array can be also created as a range, {1,6}.

Finally, typecodes. Those always start with a datatype keyword: char, short, int, long, float, double. After that, in case of an array, a star follows. When provided with a value, you can leave the star there and the shape will be figured out on its own. Otherwise, it's a series of dimensions multiplied by each other starting from dimension one.

[Array Structure]

Common structure for all variables:


A single byte, non-zero when the array position is reserved for a variable, value 1 denotes a char.


Four bytes, unsigned integer, represents length of the entire variable in array (in bytes).


Only present in arrays, every dimension is four bytes wide.


Zero encoded in four bytes to delimit type/shape from the array itself.

>value dump

Flattened array dump or several bytes to represent a number.

Array structure is never interrupted, exceeding Array length will cause unexpected behavior.:

05/02/2023 05/02/2023 12:17:49#240

[Working with the Array]

The Variable class is all you need here, as it already contains the array and manipulates it as described above. there is also a "mask", which is a multiprocessing.Array itself, and is reserved for variable names. Important methods:


Get the value of a variable from the Array.

>.modify(name, value = None)

Set variable name to a new value, zeroes by default.

>.create(name, typecode, value = None)

Reserve bytes in the Array for a brand new variable.


You can try out Viridis by downloading

The archive contains Special Expressions library ( for pattern matching within the development environment, the Environment itself (, and the esolang engine (, along with a demo folder.


My third attempt at fizzbuzz, showcases branching and parallelism in Viridis.


Hello World!


A demo where two processes try to make a value too big or too small, while the third observes them. Make your bet, launch it, sit back and enjoy the number fluctuating until one of the processes gets to +-500.


Python 3.7+, Python 3.11 recommended.

Before running install numpy, as the only non-standard package.


Viridis Development Environment is a tkinter-based GUI for working with Viridis. It only has two widgets - Text on the top and an Entry on the very bottom. TYPE COMMANDS THERE. You'd also need to change the font inside the GUI class if you're on Linux.

Some of the commands you'd need:


Lists all .vir files in curdir and subdirs.

>run hw.vir

Runs hw.vir, or any other Viridis file.

>read hw.vir

Shows the contents of hw.vir.

>edit hw.vir

Launches editor mode for this file.

>save hw.vir

Overwrites the file with current contents of the window.


Goes into editor mode without loading a file first.


Clears the screen.:

08/02/2023 08/02/2023 14:15:02#241

[Bufotes Support]

Bufotes/viridis compiler added! Even if it's more of a translator tool, it features linearization of complex complex expressions, which then can be run on any viridis interpreter!

To save the output of compile command, just add as and then the filename of target .vir, as in

>compile example.bufo as example.vir

Which is unnecessary due to .bufo files being translated automatically by the run command.